Hi there! You are currently browsing as a guest. Why not create an account? Then you get less ads, can thank creators, post feedback, keep a list of your favourites, and more!
Senior Moderator
staff: senior moderator
Original Poster
#26 Old 26th Jul 2019 at 5:59 PM
It's me again )
Another update: I removed the code for taking the book of the list, and as expected if you remove the book, it is still there for you to remove again. So removing the book from the list is working fine, it is just not wanting to destroy the book itself...There are still no script errors. Do you, @gamefreak130, or anyone else have any ideas for getting this to work? If this isn't working, perhaps i should try overhauling it a bit and having the actual book in library be moved to the sim's inventory and back, as you said.

Another question I have is about changing the game speed, I used
Gameflow.SetGameSpeed(SimIFace.Gameflow.GameSpeed.Pause, Gameflow.SetGameSpeedContext.GameStates)
for pausing the game before the menu shows up to pick a book to take out/return which works fine, and
Gameflow.SetGameSpeed(SimIFace.Gameflow.GameSpeed.Normal, Gameflow.SetGameSpeedContext.GameStates)
for after something has been chosen, however this doesn't seem to work, the game just stays paused after it has been selected.

Any help is greatly appreciated.
Advertisement
Space Pony
#27 Old 27th Jul 2019 at 3:15 AM
Quote: Originally posted by zoe22
It's me again )
Another update: I removed the code for taking the book of the list, and as expected if you remove the book, it is still there for you to remove again. So removing the book from the list is working fine, it is just not wanting to destroy the book itself...There are still no script errors. Do you, @gamefreak130, or anyone else have any ideas for getting this to work? If this isn't working, perhaps i should try overhauling it a bit and having the actual book in library be moved to the sim's inventory and back, as you said.


I've never worked with cloning objects, so I'm not sure what the problem could be. Maybe try using Actor.Inventory.TryToRemove() method to remove the book from the Sim's inventory before destroying it. It's possible that the book still may not be properly destroyed, but hopefully ErrorTrap will eventually find it and clean it up.

Quote:
Another question I have is about changing the game speed, I used
Gameflow.SetGameSpeed(SimIFace.Gameflow.GameSpeed.Pause, Gameflow.SetGameSpeedContext.GameStates)
for pausing the game before the menu shows up to pick a book to take out/return which works fine, and
Gameflow.SetGameSpeed(SimIFace.Gameflow.GameSpeed.Normal, Gameflow.SetGameSpeedContext.GameStates)
for after something has been chosen, however this doesn't seem to work, the game just stays paused after it has been selected.


Again, I'm not sure what the problem could be there, but I don't see why pausing and resuming the game speed manually is necessary -- doesn't the ObjectPickerDialog already do that?

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Senior Moderator
staff: senior moderator
Original Poster
#28 Old 27th Jul 2019 at 10:41 AM
No, without manually pausing it, time just speeds along while the window is open, which I really don't like because I usually speed through actions and so then time is stuck moving along. The version of the object picker which disabled the cancel button had a pause thing in the parameters I think, and if I remember correctly it paused the game before but didn't unpause it after, though now I'm not convinced, so I think I'll test it out and make sure I'm not just going crazy.
I'll also try the inventory thing too. Thanks
Senior Moderator
staff: senior moderator
Original Poster
#29 Old 19th Aug 2019 at 8:37 PM
New update on my progress :

I figured out why the book was not being destroyed - it turns out I was just being a bit of an idiot and was adding the original book to the list rather than the cloned one

I added in some pure scripting, so when an object is sold, it checks if it is a book, and if the book is from a library, and if so will remove the book from the list of books taken out, and deduct the price of the book as well as 500 simoleons from the household funds.
I also managed to get an alarm working, so after 48 sim hrs if the book hasn't been returned, a fine of 500 is deducted from the household funds, and this repeats every 48 hrs until the book is returned. I tested it with 3 sim hours so hopefully it is okay with the 48, but i also plan on making this value tunable, as well as the amount deducted as a fine. That is on the list of things to do, with making string tables for all the text etc, not to mention testing travelling with library books

A smaller thing I did was overwrite the name of the book merchant to be called Librarian.

My current problem is how the Library Registers work themselves. I thought using a destructor would work for if a register was sold, and the plan was to destroy all the books in the register's list, basically automatically returning the books, and to show a notification.
The code for that:

Code:
List<string> bookNames = new List<string>();

            foreach (KeyValuePair<Book, ulong> entry in bookOwner)
            {
                bookNames.Add(entry.Key.Title);
                Book book = entry.Key;
                bookOwner.Remove(book);
                book.Destroy();
            }
            Sim.ActiveActor.ShowTNSIfSelectable("Due to the closure of a library, the following books have been automatically returned: " + bookNames, StyledNotification.NotificationStyle.kSystemMessage);


This didn't work, so I added it to the pure scripting part, by checking if the object sold was a library register object and this also didn't work! (even the notification did not show up, so i suppose the whole section of code is not being called.)
However I noticed that when the register is sold (or deleted with testing cheats + shift click and delete), it doesn't actually affect the list of books taken out. When another register is added, you are still able to return the books previously taken out, and in fact, when I added a second register to the lot (and a third to a different lot) , the same list of books taken out is shown that you can return. This surprised me, as I thought the list (it is actually a dictionary with the book as the key, the sim who took it out as the value) was within the object itself, and the object being each individual register. But it seems like what books have been taken out is global to all library registers in the world. This on its own isn't really a problem for me (though I would like to understand why this is happening in this way!) but I need a way to automatically return the books if the registers are sold/deleted and there is no way for the books to be returned.

Another problem I am having is charging the sim a fine when they don't have enough money. I tried setting it so that if the sim has less money than what is needed to be fined, the money is set to 0 simoleons:

Code:
//when a library book is sold
if (Sim.ActiveActor.FamilyFunds < (500 + bookSold.BookValue)) Sim.ActiveActor.ModifyFunds(0 - Sim.ActiveActor.FamilyFunds);
Sim.ActiveActor.ModifyFunds(0 - (500+bookSold.BookValue));


I honestly don't know what is happening, but sometimes the funds end up as the price of the book, sometimes some amount a bit less than the book is added, and sometimes a small amount is taken away eg 15 simoleons. I'm guessing it is to do with when the Sim.Active.FamilyFunds value is taken - ie. before or after the book is sold - but really it doesn't seem to behave the same way each time. Maybe this isn't the right way to implement it, and i should use the household bills, though I haven't looked into using those properly yet.

Thanks in advance for any help
Space Pony
#30 Old 27th Aug 2019 at 5:04 AM
Quote: Originally posted by zoe22
When another register is added, you are still able to return the books previously taken out, and in fact, when I added a second register to the lot (and a third to a different lot) , the same list of books taken out is shown that you can return. This surprised me, as I thought the list (it is actually a dictionary with the book as the key, the sim who took it out as the value) was within the object itself, and the object being each individual register. But it seems like what books have been taken out is global to all library registers in the world. This on its own isn't really a problem for me (though I would like to understand why this is happening in this way!) but I need a way to automatically return the books if the registers are sold/deleted and there is no way for the books to be returned.


Is your book dictionary static or located somewhere other than the LibraryRegister class (i.e. within an interaction class)? Those are the only two things I could think of that would explain a global book list.

Quote: Originally posted by zoe22
Another problem I am having is charging the sim a fine when they don't have enough money. I tried setting it so that if the sim has less money than what is needed to be fined, the money is set to 0 simoleons:

Code:
//when a library book is sold
if (Sim.ActiveActor.FamilyFunds < (500 + bookSold.BookValue)) Sim.ActiveActor.ModifyFunds(0 - Sim.ActiveActor.FamilyFunds);
Sim.ActiveActor.ModifyFunds(0 - (500+bookSold.BookValue));


I honestly don't know what is happening, but sometimes the funds end up as the price of the book, sometimes some amount a bit less than the book is added, and sometimes a small amount is taken away eg 15 simoleons. I'm guessing it is to do with when the Sim.Active.FamilyFunds value is taken - ie. before or after the book is sold - but really it doesn't seem to behave the same way each time. Maybe this isn't the right way to implement it, and i should use the household bills, though I haven't looked into using those properly yet.


Honestly, I have no idea what the problem could be here. My initial thought is that you have no "else" between your insufficient funds check and the full price of the fine, so if the sim has insufficient funds, they will essentially be fined twice; however, that shouldn't be causing problems like the ones you describe. I would try adding to household bills to see if a similar issue occurs. You can use the following line to add to the household bills:

Code:
Sim.ActiveActor.Household.UnpaidBills += num;


Where "num" is the amount you want to add as a positive integer.

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Virtual gardener
staff: administrator
#31 Old 27th Aug 2019 at 3:00 PM
I think you're right here indeed Gamefreak, I think the issue what's going on here as well is that code is not exactly sure what to do when it meets the boolean (Aka if the "If" is true or false) Now, I think this is the notation you're actually looking for?

Code:
    if (Sim.ActiveActor.FamilyFunds < (500 + bookSold.BookValue))
    {
        Sim.ActiveActor.ModifyFunds(0 - Sim.ActiveActor.FamilyFunds);
    }
    else 
    {
        Sim.ActiveActor.ModifyFunds(0 - (500+bookSold.BookValue));
    }


So, the if statement actually can be different according to your if statement. If we narrow it down, you're basically saying (with examples of course):

- If the Family funds is less than 500 + 72 (this can be a random book price, making this 572) then do this.
- If the family funds is less than 500 + 150 (this being also a random book price example, making this 650) then do this.

Sorry for barging in here Just figured this could be helpful

Actually, relooking at it, I always like to make sure that the statement can either be "Less" or "Equal to" by doing:
Code:
    if (Sim.ActiveActor.FamilyFunds <= (500 + bookSold.BookValue))


that way you always know that if the price is exactly the same as the family funds it will still charge them
Senior Moderator
staff: senior moderator
Original Poster
#32 Old 27th Aug 2019 at 6:26 PM Last edited by zoe22 : 27th Aug 2019 at 6:37 PM.
Ahh thanks to both of you! You're right, I forgot the "else"
And gamefreak, yes the dictionary is static so i guess that explains why it is global. It is within the LibraryRegister class.
However, I don't know how to use the non-static dictionary from the AskForBook and ReturnBooks classes - it says an object reference is required. It works in the CheckForBook() method, which is called when an book is sold, and this is just inside the LibraryRegister class. So it's only a problem for when I'm trying to access the dictionary in the Interaction classes inside the LibraryRegister class, I think at least

Here is my entire code, though it might be a bit all over the place
Space Pony
#33 Old 27th Aug 2019 at 7:28 PM Last edited by Battery : 27th Aug 2019 at 7:48 PM.
Hey Zoe22 . 1. you need references to the registers where the books where taken from see Spoiler code below . 2. It is good style to always use the {} for statements so always use .
Code:
if (condition)
{
       Action
}
else
{
      OtherAction
}
This prevents some errors one might overlook otherwise So use the { and } . . . . . I have not checked the code below in the Game but it compiles now without errors . .
Senior Moderator
staff: senior moderator
Original Poster
#34 Old 27th Aug 2019 at 9:51 PM
Thank you Battery! I will try that out tomorrow.
Also thanks for the tip about using {}, I didn't realise it can cause errors eek
Senior Moderator
staff: senior moderator
Original Poster
#35 Old 29th Aug 2019 at 12:43 PM Last edited by zoe22 : 29th Aug 2019 at 12:53 PM.
Hi again,
There are still problems with fining the sim when the have less money than can be fined, though I think I can see what is happening - it looks like the funds are being made to be 0 simoleons, before the money from selling the book is added. So say my sim has $12, sells a library book worth $65, the +$53 pops up and they end up with the $65 in total. Then if they sell another library book worth $135, the +$70 pops up and the end up with the $135. Then if they sell a $130 library book, the -$5 pops up and they end up with $130. I feel like that's an overly complicated explanation but I am pretty sure this is what happening, as it explains the seemingly random amounts added and taken away before i fixed my If and Else statements.

Would it be a better idea to use the household bills instead?

On the problem of getting rid the library register, when i shift click delete it, the book is still in the inventory, but has no consequences from being sold. When I sell the register, only one sim's books disappeared, and another still had theirs again with no fine for selling, and no notification shows up.
The code that is called when a register is sold:

Code:
public void OnSoldLibraryRegister()
        {
            List<string> bookNames = new List<string>();

            foreach (KeyValuePair<Book, ulong> entry in bookOwner)
            {
                bookNames.Add(entry.Key.Title);
                Book book = entry.Key;
                bookOwner.Remove(book);
                book.Destroy();
            }
            Sim.ActiveActor.ShowTNSIfSelectable("Due to the closure of a library, the following books have been automatically returned: " + bookNames, StyledNotification.NotificationStyle.kSystemMessage);

        }


What should I do to reliably return the books when a register is destroyed or sold?

Space Pony
#36 Old 29th Aug 2019 at 2:41 PM
Quote: Originally posted by zoe22
Hi again,
There are still problems with fining the sim when the have less money than can be fined, though I think I can see what is happening - it looks like the funds are being made to be 0 simoleons, before the money from selling the book is added. So say my sim has $12, sells a library book worth $65, the +$53 pops up and they end up with the $65 in total. Then if they sell another library book worth $135, the +$70 pops up and the end up with the $135. Then if they sell a $130 library book, the -$5 pops up and they end up with $130. I feel like that's an overly complicated explanation but I am pretty sure this is what happening, as it explains the seemingly random amounts added and taken away before i fixed my If and Else statements.

Would it be a better idea to use the household bills instead?


It sounds like you're on the right track; the way you describe it, it sounds like the fine is taken before the book is actually sold and the sim receives the money. Thus, the sim's funds are reduced to 0 from the fine, but they are then credited the value of the book; that might just be the order in which the events are handled. I would try using the household bills, because that way you can add the full fine to the bills, rather than having to reduce the penalty -- gameplay-wise, that makes more sense to me. If you insist on an immediate, variable fine, then you can try using an alarm or a persistable stopwatch with a short delay; you can take a look at my Job Overhaul mod for an example of global alarms.

Quote: Originally posted by zoe22
On the problem of getting rid the library register, when i shift click delete it, the book is still in the inventory, but has no consequences from being sold. When I sell the register, only one sim's books disappeared, and another still had theirs again with no fine for selling, and no notification shows up.

What should I do to reliably return the books when a register is destroyed or sold?


I'm still kind of stumped on this one. The fact that the notification does not appear suggests that an unhandled exception occurred somewhere in your foreach loop; perhaps it would work if you used a null check on entry.Key before you add the title to bookNames and destroy the book.

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Space Pony
#37 Old 29th Aug 2019 at 4:53 PM Last edited by Battery : 29th Aug 2019 at 5:05 PM.
Hey zoe22, since you shift click deleting the register your OnSoldLibraryRegister will not be called (since it gets destroyed and not sold) in this case make good old c++ style destructor like that:
Code:
    	~LibraryRegister()
    	{
	       Sims3.UI.StyledNotification.Show(new Sims3.UI.StyledNotification.Format("Object Deleted", Sims3.UI.StyledNotification.NotificationStyle.kGameMessagePositive)); //just for debbuging purpose
    	       OnSoldLibraryRegister();
    	}
If you dont get the message then you probably have a memory leak E: if the register gets lost in some way you could also just remove the book from the sims inventory yourself to make sure it gets "collected"
Senior Moderator
staff: senior moderator
Original Poster
#38 Old 29th Aug 2019 at 6:14 PM
Hi Battery
I did actually originally have a destructor but I must have deleted it! So I'll add that back in.
A memory leak? Sounds bad...
It's true I could remove the books myself, but I thought if I'm going to upload the mod for download, I'd like to consider as many situations as possible so things don't go wrong for people.
But thank you for your response, I will do some more testing

And thanks as well, gamefreak. I think you're right about using the household bills - it makes more sense, it's just harder to test hehe.
Space Pony
#39 Old 29th Aug 2019 at 6:33 PM
Quote: Originally posted by Battery
Hey zoe22,
since you shift click deleting the register your OnSoldLibraryRegister will not be called (since it gets destroyed and not sold)


Ah, thanks Battery, I hadn't even realized that! An alternative to a destructor is to change your event handler type from "kSoldObject" to "kEventObjectDisposed." This way, your code should work with minimal changes; even the book fines should work then, since the actual disposal of the book is guaranteed to take place after the household funds have been credited for selling the book!

EDIT: I realize as I type this that traveling with books in the inventory may be a major issue, since your fine alarms will not carry over between worlds, and selling loaned books will not fine Sims because technically the register it came from no longer exists in the current world. You may be able to use a PersistableStatic Tuple to store the book, the sim, and the register it came from across multiple worlds, but let's make sure it all works in one world first before we start undertaking large changes like that

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Senior Moderator
staff: senior moderator
Original Poster
#40 Old 29th Aug 2019 at 8:39 PM
Thank you gamefreak! That would be a really good idea as it would kill 2 birds with one stone if it works as planned! I also just realised that if a book is sold, even if I want to fine the sim through household bills, I'd better still take away the money earned from selling immediately.

And definitely I'll cross the bridge about travelling when I get to it!
Senior Moderator
staff: senior moderator
Original Poster
#41 Old 30th Aug 2019 at 4:22 PM
So, I tried kEventObjectDisposed, and it works great for the books being sold, the fine works perfectly! However it still doesn't work for when the register is sold or deleted. The books are still in the sims' inventories as regular books - can be sold with no fine. I could try a destructor again but I am pretty sure it didn't work last time.

Here is the package file for my mod as Battery suggested it would be helpful to see how it works
It is a clone of the consignment register that came with Ambitions.
Attached files:
File Type: 7z  zoeoe_registerlibraryMod.7z (26.3 KB, 4 downloads) - View custom content
Space Pony
#42 Old 30th Aug 2019 at 6:17 PM Last edited by Battery : 1st Sep 2019 at 10:03 PM.
Quote: Originally posted by zoe22
So, I tried kEventObjectDisposed, and it works great for the books being sold, the fine works perfectly! However it still doesn't work for when the register is sold or deleted. The books are still in the sims' inventories as regular books - can be sold with no fine. I could try a destructor again but I am pretty sure it didn't work last time.

Here is the package file for my mod as Battery suggested it would be helpful to see how it works
It is a clone of the consignment register that came with Ambitions.


Ok i got the reasons for your problem ill be back when ive coded the solution in a bit
From the Region where kEventObjectDisposed is fired
Code:
	if (!fromDtor)
	{
		if (this.InInventory && this.ItemComp == null && this.mOwnerLot != null && this.mOwnerLot.Household != null && this.mOwnerLot.Household.SharedFamilyInventory != null && this.mOwnerLot.Household.SharedFamilyInventory.Inventory != null)
		{
			this.mOwnerLot.Household.SharedFamilyInventory.Inventory.RemoveByForce(this, true);
		}
		if (this.mObjComponents != null)
		{
			for (int i = 0; i < this.mObjComponents.Count; i++)
			{
				this.mObjComponents[i].Dispose();
			}
			this.mObjComponents = null;
		}
		GC.SuppressFinalize(this);
	}
	if (this.ObjectDisposed != null)
	{
		this.ObjectDisposed(this);
	}
	EventTracker.SendEvent(EventTypeId.kEventObjectDisposed, null, this);

As you can see the Event is fired AFTER the object is disposed so it is null at that point, ergo you cant do any actions on it.
override the dispose method and tie it to the OnObjectSold method

E: Do you want the Bookvalue+Fine to be substracted like when selling the book when the register gets sold and or deleted ?

E1: I have attached a soluion to your problem let me know if i should explain what was changed
E2: Books only got removed from one actor because you used Sim.ActiveActor for your fining

E3: Removed irritating outdated download
Senior Moderator
staff: senior moderator
Original Poster
#43 Old 1st Sep 2019 at 9:22 PM
Hi again,
I just want to give a quick update:
Thank you for the code, Battery, I have used it to modify mine as I wanted it to work slightly differently.
The OnBookLostOrSold function, I just needed to be OnBookSold, as if the register is deleted and the book is removed, then there doesn't need to be a fine, only when the book is sold.

Code:
public void OnBookSold(ulong simdesc, Book bookSold)
        {
            try
            {
                SimDescription tempdesc = SimDescription.Find(simdesc);

                if (tempdesc == null)
                {
                    StyledNotification.Show(new StyledNotification.Format("No owner", StyledNotification.NotificationStyle.kGameMessagePositive));
                    return;
                }
                if (tempdesc.FamilyFunds < (500 + bookSold.BookValue))
                {
                    tempdesc.ModifyFunds(-tempdesc.FamilyFunds);
                }

                else
                {
                    tempdesc.ModifyFunds(-(500 + bookSold.BookValue));
                }
                if (tempdesc.Household != Sim.ActiveActor.Household)
                {
                    return;
                }
                
                Sim.ActiveActor.ShowTNSIfSelectable(tempdesc.FirstName + " has been fined 500 Simoleons for selling a library book: " + bookSold.Title.ToString() + ". Return your books next time!", StyledNotification.NotificationStyle.kGameMessageNegative);
            }
            catch
            {
            }
            
        }


I added the overrided Dispose method from your code too, to implement the code where books are destroyed and the player notified:

Code:
 public override void Dispose()
        {
            string bookNames = "";

            foreach (KeyValuePair<Book, ulong> entry in bookOwner)
            {
                Book book = entry.Key;
                bookNames += book.Title + "  value: " + book.Value + "\n";
                bookOwner.Remove(book);
                book.Destroy();
            }

            Sim.ActiveActor.ShowTNSIfSelectable("Due to the closure of a library, the following books have been automatically returned: " + bookNames, StyledNotification.NotificationStyle.kSystemMessage);
            base.Dispose();
        }


I did test it quickly, however, and it still does not seem to work properly. I think again only the books from one sim are being destroyed. This has nothing to do with the FineSim method, as that is called when the alarm for book due date is finished, not when a book (or a register) is sold. The code for getting rid of the books when a register is disposed has nothing to do with an individual sim, so I'm not sure about that.

The other thing I realised was using the kObjectDisposed rather than kObjectSold, was that if a book is disposed and not sold (perhaps when a register is disposed), the sim would be fined, when they should only be fined when they sell a book. Perhaps I will use a short delay like gamefreak suggested.

Anyway, I haven't messed around with it much yet so I will spend a bit more time to see if I can work anything out, but i just wanted to let you know that I didn't ignore Battery's code
To be honest, it's giving me a bit of a headache at this point, so I think I might come back to it in a few days or so with a clearer mind.
Thanks everyone for your help so far

I'll also leave my whole code again, just in case I've done something stupid when figuring out Battery's code

Space Pony
#44 Old 1st Sep 2019 at 9:50 PM Last edited by Battery : 1st Sep 2019 at 10:04 PM.
If you took the code i uploaded here youre right it didnt work i should have taken down the download after i made the new version.
The "New" version is the one from discord it might be what you wanted. youll still be fined but you can rip that out of the code and you should be good to go -the mentioned fine system issues


Senior Moderator
staff: senior moderator
Original Poster
#45 Old 10th Sep 2019 at 3:06 PM
I've finally got round to trying out the new version of your code, Battery, and everything is working great so far! Bless you! The fining works when there are insufficient funds, and the books are properly destroyed when a register is destroyed or sold.

My next steps will be to make sure no problems occur when sims move out, the household is changed, and sims travel abroad.

Thinking about this, I realise what you meant (Battery) about changing the FineSim() method, as it would fine the household even if the book is not part of the household. Would there be a way to tie the alarm to the sim who owns the book, or to the book taken out, or would a better option be to just return any books that don't belong to the active household? I'm not sure how to do this though, would it be using the event listeners? I see there is a kMoveOutOfTown and kMovedHousehold and a few similar ones - not sure if these are appropriate?

Space Pony
#46 Old 11th Sep 2019 at 5:14 PM
Quote: Originally posted by zoe22
I've finally got round to trying out the new version of your code, Battery, and everything is working great so far! Bless you! The fining works when there are insufficient funds, and the books are properly destroyed when a register is destroyed or sold.

My next steps will be to make sure no problems occur when sims move out, the household is changed, and sims travel abroad.

Thinking about this, I realise what you meant (Battery) about changing the FineSim() method, as it would fine the household even if the book is not part of the household. Would there be a way to tie the alarm to the sim who owns the book, or to the book taken out, or would a better option be to just return any books that don't belong to the active household? I'm not sure how to do this though, would it be using the event listeners? I see there is a kMoveOutOfTown and kMovedHousehold and a few similar ones - not sure if these are appropriate?



Hey Zoe22,

the probably easiest way would be to loop through the BookOwner Dictionary each time an alarm fires, if the dictionary contains an SimdescriptionID of any sim from the current household fine the household.
Of course this depends on how excactly the system should work eg should all households with borrowed books be fined or just the active one ?
And last but certainly not least the suggestion above can be optimized but how depends on your needs
Senior Moderator
staff: senior moderator
Original Poster
#47 Old 10th Oct 2019 at 7:47 PM
Hi again.

It's been while but recently looking at this project has made my brain start to implode so
But I am back and hopefully will make some more progress.

At the moment I am wanting to sort out the fining business. At the moment I feel it is easiest for only active sims to be fined for overdue books, and so I have been trying to work out how to do this.
In the Library Register class I have:
Code:
private AlarmHandle handle;

And in the AskForBook class I have:
Code:
RegisterPointer.handle = bookToAdd.AddAlarmRepeating(1f, TimeUnit.Hours, new AlarmTimerCallback(RegisterPointer.FineSim), "TimeUntilFine", AlarmType.AlwaysPersisted); //1 hour for testing purposes

RegisterPointer is the LibraryRegister variable made by Battery to get the register from the base class, in order to have the book chosen to be taken out added to the register's dictionary which stores the book and sim description.

I then have the FineSim method just in the LibraryRegister class which currently just fines the active household and works okay, but I need it to first check that the sim who took the book is in the active household.

My problem is getting the information I need in the FineSim Class. I tried changing it to take the parameter of a Book, and then calling:
Code:
RegisterPointer.handle = bookToAdd.AddAlarmRepeating(1f, TimeUnit.Hours, new AlarmTimerCallback(RegisterPointer.FineSim(bookToAdd)), "TimeUntilFine", AlarmType.AlwaysPersisted); 

but it doesn't seem to like the parameter as it is no longer recognised as a method. It just says "Method name expected". I guess it is just to do with the way the alarm callbacks are called, as it doesn't use brackets when calling FineSim, but I can't find how to pass the variable to the FineSim method. If I can do this, I believe I could then find the simdesc in the bookOwner dictionary for that book in order to check if they are in the active household? So if you can help me out that would be great

Thanks
Space Pony
#48 Old 10th Oct 2019 at 9:33 PM
Quote: Originally posted by zoe22
My problem is getting the information I need in the FineSim Class. I tried changing it to take the parameter of a Book, and then calling:
Code:
RegisterPointer.handle = bookToAdd.AddAlarmRepeating(1f, TimeUnit.Hours, new AlarmTimerCallback(RegisterPointer.FineSim(bookToAdd)), "TimeUntilFine", AlarmType.AlwaysPersisted); 

but it doesn't seem to like the parameter as it is no longer recognised as a method. It just says "Method name expected". I guess it is just to do with the way the alarm callbacks are called, as it doesn't use brackets when calling FineSim, but I can't find how to pass the variable to the FineSim method. If I can do this, I believe I could then find the simdesc in the bookOwner dictionary for that book in order to check if they are in the active household? So if you can help me out that would be great

Thanks


When creating a new AlarmTimerCallback, you only put in the name of the method without parentheses or arguments. The assumption the game has is that the method you point to takes no arguments and does not return anything, which does not appear to be the case here.

If you really need the local variable bookToAdd in order to do something, you can use what's called an anonymous delegate to directly insert whatever code you want run into the AlarmTimerCallback and work around the limitation. For example:

Code:
RegisterPointer.handle = bookToAdd.AddAlarmRepeating(1f, TimeUnit.Hours, new AlarmTimerCallback(delegate()
{
    //Just an example of what you could do using anonymous delegates; place more relevant code here
    if (bookToAdd is MedicalJournal)
    {
        Sims3.UI.StyledNotification.Show(new Sims3.UI.StyledNotification.Format("This is a medical journal!", Sims3.UI.StyledNotification.NotificationStyle.kDebugAlert));
    }
}), "TimeUntilFine", AlarmType.AlwaysPersisted); 


You could also use what's called a lambda expression to achieve the same result:

Code:
RegisterPointer.handle = bookToAdd.AddAlarmRepeating(1f, TimeUnit.Hours, new AlarmTimerCallback(() =>
{
    //Again, just an example
    if (bookToAdd is MedicalJournal)
    {
        Sims3.UI.StyledNotification.Show(new Sims3.UI.StyledNotification.Format("This is a medical journal!", Sims3.UI.StyledNotification.NotificationStyle.kDebugAlert));
    }
}), "TimeUntilFine", AlarmType.AlwaysPersisted); 


In this instance, the lambda expression will compile into a delegate and is essentially syntactic sugar.

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Senior Moderator
staff: senior moderator
Original Poster
#49 Old 11th Oct 2019 at 6:28 PM
That's great, gamefreak!
I'm going to do some proper testing to double check that everything works properly so far. What I have done now for fining, is check if the sim who has taken out the book is in the active household, and if not it will just return the book. So hopefully that will take care of sims that move out of the household.

Then I think all that is mainly left to do is to sort out situations like when sims travel. You suggested a PersistableStatic Tuple? (ahem no idea what that is). Would it be easier to automatically return books before sims travel etc or better to carry the information through. Just thought of some more scenarios - when sims go to boarding school, or parents go on those vacation opportunities that come with generations. Do you know anything about those and how they work with alarms?

Thanks for all your help
Space Pony
#50 Old 12th Oct 2019 at 7:52 AM
Quote: Originally posted by zoe22
That's great, gamefreak!
I'm going to do some proper testing to double check that everything works properly so far. What I have done now for fining, is check if the sim who has taken out the book is in the active household, and if not it will just return the book. So hopefully that will take care of sims that move out of the household.

Then I think all that is mainly left to do is to sort out situations like when sims travel. You suggested a PersistableStatic Tuple? (ahem no idea what that is). Would it be easier to automatically return books before sims travel etc or better to carry the information through. Just thought of some more scenarios - when sims go to boarding school, or parents go on those vacation opportunities that come with generations. Do you know anything about those and how they work with alarms?

Thanks for all your help


Good job for planning for all those edge cases; that's what programming is all about

Whenever Sims are sent to boarding school or free vacations, what happens -- or what's supposed to happen, as the system is rather unstable -- is the Sim object itself is destroyed, but the SimDescription as well as all their inventory objects still exist and are used to recreate the Sim upon their "return." Since you're targeting SimDescriptions, there should be no real problems with free vacations. However, you may just want to return any books a Sim has in their inventory before they're sent off to boarding school, which can be done through a kSentSimToBoardingSchool EventListener; then, in order to retrieve the student, you would have to use e.Target, rather than e.Actor.

Regarding traveling, it would be much less work to just return the books before traveling occurs; the problem is, unless you're traveling to the future, it doesn't look like there's an easy way to listen for when Sims initially leave for vacation. You might try using kVacationTelemetryInfo, but I'm not sure if that'd work reliably.

"The Internet is the first thing that humanity has built that humanity doesn't understand, the largest experiment in anarchy that we have ever had." - Eric Schmidt

If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Page 2 of 3
Back to top