- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- What is the code that makes Imaginary Friends invisible?
- Site Map >
- Modding and Creation >
- Sims 3 Creation >
- Modding Discussion >
- What is the code that makes Imaginary Friends invisible?
Posts: 175
Thanks: 175 in 1 Posts
Posts: 437
Thanks: 5330 in 22 Posts
So, as some of you might know, I'm working on a ghost overhaul. I've been wanting to make ghosts be visible only to certain sims, like ghost hunters and all that. To achieve this objective, I plan on trying to use the Imaginary Friend code. I'm searching for what makes them invisible in Ilspy, but I can't find the exact piece of code that produces this effect. Could someone help me? |
I think what you're looking for is Sims3.Gameplay.ActorSystems.OccultImaginaryFriend.RefreshVisibility(), which is called any time the selected Sim changes through an event listener on kEventSimSelected.
public bool RefreshVisibility(bool immediate) { if (this.mSimDescription == null) { return false; } Sim createdSim = this.mSimDescription.CreatedSim; if (createdSim == null) { return false; } bool flag = false; if (this.IsReal) { flag = true; } else { Sim selectedActor = PlumbBob.SelectedActor; SimDescription simDescription = (selectedActor == null) ? null : selectedActor.SimDescription; if (simDescription != null && (simDescription.SimDescriptionId == this.mOwnerSimDescId || selectedActor == createdSim)) { flag = true; } else { SimDescription simDescription2 = SimDescription.Find(this.mOwnerSimDescId); Sim sim = (simDescription2 == null) ? null : simDescription2.CreatedSim; if (sim != null && sim.IsDying()) { flag = true; } } } float fadeTime = immediate ? 0f : GameObject.kGlobalObjectFadeTime; if (flag) { createdSim.FadeIn(false, fadeTime); } else { createdSim.FadeOut(false, false, fadeTime); } Audio.MuteAllSounds(createdSim.ObjectId, !flag); return flag; }
Basically, if the selected Sim is either the owner of the imaginary friend or the imaginary friend itself (or if the owner is dying, for some reason), then Sim.FadeIn() is called on the imaginary friend to show it if it's already hidden. Otherwise, Sim.FadeOut() is called to hide it if it's not already hidden. The sounds that the imaginary friend is making are also muted or unmuted accordingly.
You could probably copy most of this function and just replace "simDescription.SimDescriptionId == this.mOwnerSimDescId" with whatever condition you want on the selected actor. You might also consider removing the death check.
If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Posts: 175
Thanks: 175 in 1 Posts
Posts: 437
Thanks: 5330 in 22 Posts
@gamefreak130 , how could I set multiple independent conditions to the visibility of the ghosts? I have three methods to see ghosts in mind: Having a certain custom moodlet, being in the Ghost Hunter career and reaching level 5 in the spellcasting skill. |
Just keep chaining the conditions using the or (||) operator like so:
if (simDescription != null && (simDescription.Occupation is GhostHunter || simDescription.SkillManager?.GetElement(SkillNames.Spellcraft)?.SkillLevel >= 5 || simDescription.CreatedSim.BuffManager?.HasElement(yourBuffGuid) || selectedActor == createdSim))
If the simDescription exists (is not null), and any one of the conditions in the inner parentheses is true, then the if statement will proceed, setting "flag" to true and fading in the ghost.
If you enjoy the mods I put out, consider supporting me on patreon: www.patreon.com/Gamefreak130
Posts: 175
Thanks: 175 in 1 Posts
Posts: 175
Thanks: 175 in 1 Posts
public bool RefreshVisibility(bool immediate) { if (mSimDescription == null) { return false; } Sim ghostSim = mSimDescription.IsGhost; if (ghostSim == null) { return false; } bool flag = false; if (IsReal) { flag = true; } else { Sim selectedActor = PlumbBob.SelectedActor; SimDescription simDescription = (selectedActor == null) ? null : selectedActor.SimDescription; if (simDescription != null && (simDescription.Occupation is GhostHunter || simDescription.SkillManager?.GetElement(SkillNames.Spellcraft)?.SkillLevel >= 5 || simDescription.CreatedSim.BuffManager?.HasElement(yourBuffGuid) || selectedActor == ghostSim)) { flag = true; } } float fadeTime = immediate ? 0f : GameObject.kGlobalObjectFadeTime; if (flag) { createdSim.FadeIn(false, fadeTime); } else { createdSim.FadeOut(false, false, fadeTime); } Audio.MuteAllSounds(createdSim.ObjectId, !flag); return flag; }
Posts: 175
Thanks: 175 in 1 Posts
Sim createdSim = mSimDescription.IsGhost;
What should I do? Context:
public class Visibility { public bool RefreshVisibility(bool immediate) { if (mSimDescription == null) { return false; } Sim createdSim = mSimDescription.IsGhost; if (createdSim == null) { return false; } bool flag = false; if (IsReal) { flag = true; } else { Sim selectedActor = PlumbBob.SelectedActor; SimDescription simDescription = (selectedActor == null) ? null : selectedActor.SimDescription; if (simDescription != null && (simDescription.Occupation is GhostHunter || (simDescription.SkillManager.HasElement(SkillNames.Spellcraft) && simDescription.SkillManager.GetElement(SkillNames.Spellcraft).SkillLevel >= 5) || simDescription.CreatedSim.BuffManager.HasElement(0x15DABBECF72A9084) || selectedActor == createdSim)) { flag = true; } } float fadeTime = immediate ? 0f : GameObject.kGlobalObjectFadeTime; if (flag) { createdSim.FadeIn(false, fadeTime); } else { createdSim.FadeOut(false, false, fadeTime); } Audio.MuteAllSounds(createdSim.ObjectId, !flag); return flag; } public SimDescription mSimDescription; public bool IsReal { get { return mIsReal; } set { mIsReal = value; } } public bool mIsReal; }
Posts: 3,860
Thanks: 8537 in 67 Posts
So, just for other people to understand what the CS0029 error is, it's an error when you're trying to assign a value to a variable but both have a different type.
For instance, this will give you an CS0029 error:
string iAmAString = "Hello!"; int iAmInt = iAmAString
The same thing is the case when assigning a SimDescription type to a Sim. Because the Sim is the "Whole" sim and the SimDescription is... well, how you'd "Describe" the sim as their being (Career, traits, skills, lovers, etc). At least that's how I remember them. So Assigning Sim to a Simdescription won't work like you did here:
Sim createdSim = mSimDescription.IsGhost;
SimDescription createdSim = mSimDescription.IsGhost;
OR do this:
Sim createdSim = null; //Later on in your code when you need CreatedSim you do: createdSim = base.Actor; if(createdSim.SimDescription.IsGhost) { blah blah blah }
Posts: 175
Thanks: 175 in 1 Posts
public bool RefreshVisibility(bool immediate) { if (targetDescription == null) { return false; } Sim createdSim = targetDescription.CreatedSim; if (createdSim == null) { return false; } bool flag = false; if (!targetDescription.IsGhost) { flag = false; } else { Sim selectedActor = PlumbBob.SelectedActor; SimDescription simDescription = (selectedActor == null) ? null : selectedActor.SimDescription; if (simDescription != null && (simDescription.Occupation is GhostHunter || (simDescription.SkillManager.HasElement(SkillNames.Spellcraft) && simDescription.SkillManager.GetElement(SkillNames.Spellcraft).SkillLevel >= 5) || simDescription.CreatedSim.BuffManager.HasElement(0x15DABBECF72A9084) || selectedActor == createdSim)) { flag = true; } } float fadeTime = immediate ? 0f : GameObject.kGlobalObjectFadeTime; if (flag) { createdSim.FadeIn(false, fadeTime); } else { createdSim.FadeOut(false, false, fadeTime); } Audio.MuteAllSounds(createdSim.ObjectId, !flag); return flag; } public SimDescription mSimDescription; public SimDescription targetDescription; }
Is there anything here that would be prejudicial to my goal? Or is everything okay, and how could I call upon it to create the desired effect?
Posts: 3,860
Thanks: 8537 in 67 Posts
public static void OnWorldLoadFinishedHandler(object sender, System.EventArgs e) { foreach (Sim sim in Sims3.Gameplay.Queries.GetObjects<Sim>()) { if (sim != null && sim.SimDescription.IsGhost) { RefreshVisibility(true); } } }
For more info on global mods I'd check this out: http://www.simlogical.com/ContentUp..._script_mod.pdf
Posts: 175
Thanks: 175 in 1 Posts
Posts: 3,860
Thanks: 8537 in 67 Posts
@Lyralei , I'm getting error CS0120 when trying to use the RefreshVisibility boolean. What should I do? |
public static bool RefreshVisibility(bool immediate)
If it were to be an interaction, I'd suggest doing ' base.target.FUNCTIONNAME' or 'base.actor.FUNCTIONNAME'
Posts: 175
Thanks: 175 in 1 Posts
Posts: 3,860
Thanks: 8537 in 67 Posts
@Lyralei , the problem is... That it isn't exactly an interaction. It would work every time the selected sim changes - And I don't know exactly how to call upon such a thing. I tried this method that you suggested, but it gave me no results. |
So, if I were you, I'd modify the invisible code thing a bit more to parse in a sim as well in your parameters. That way, you don't necessarily need the whole 'createdSim' stuff you're defining (which was useful in the case of an Occult, since you'd already have that kind of data).
Here's what I'd change:
public bool RefreshVisibility(bool immediate, Sim sim) { if (sim == null) { return false; } bool flag = false; if (!sim.SimDescription.IsGhost) { flag = false; } else { // THis should probably need some testing, but I can see that this could work. Sim selectedActor = PlumbBob.SelectedActor; SimDescription simDescription = (selectedActor == null) ? null : selectedActor.SimDescription; if (simDescription != null && (simDescription.Occupation is GhostHunter || (simDescription.SkillManager.HasElement(SkillNames.Spellcraft) && simDescription.SkillManager.GetElement(SkillNames.Spellcraft).SkillLevel >= 5) || simDescription.CreatedSim.BuffManager.HasElement(0x15DABBECF72A9084) || selectedActor == createdSim)) { flag = true; } } float fadeTime = immediate ? 0f : GameObject.kGlobalObjectFadeTime; if (flag) { sim.FadeIn(false, fadeTime); } else { sim.FadeOut(false, false, fadeTime); } Audio.MuteAllSounds( sim.ObjectId, !flag); return flag; } }
And then basically you do this:
public static void OnWorldLoadFinishedHandler(object sender, System.EventArgs e) { foreach (Sim sim in Sims3.Gameplay.Queries.GetObjects<Sim>()) { // Either this: if (sim != null && sim.SimDescription.IsGhost) // Or this: if (sim != null) { RefreshVisibility(true, sim); } } }
And voila! I did make an error yesterday thinking that true means it's invisible, but it's actually the opposite. So if we put in false then the sim will turn invisible. Keep that in mind though!
Now I can see instances where a sim would need to see them, which means we need to set it back to 'true'. I'd say for those instances try looking into Broadcaster stuff
EDIT: I went a bit back to some older threads you made to get a better understanding of how this needs to work, but I did come across this interesting thread: https://modthesims.info/showthread....172#post5706172
Where this code is, in the case of the OccultImaginaryfriend code is always being executed for when a sim is selected (And has an Imaginary friend, hence the 'owner' variable). Instead, I'd turn the thought around. Figure out who happen to be ghosts and give them a broadcaster, so when people are around them, you execute the RefreshVisibility code (Where we also do checks of course if the sim in the broadcast area can even see them). And there you go!
The broadcast would then be the thing you'd want to add to the onWorldFinished code, rather than the RefreshVisbility. ANd then just execute the RefreshVisibilty code inside the broadcaster
Make sure you check this thread for that where we've discussed it before: https://modthesims.info/showthread.php?t=651733
Posts: 175
Thanks: 175 in 1 Posts
new public static ISoloInteractionDefinition Singleton = new Definition();
Thus, when I try doing this on the instantiator class:
sim.AddInteraction(CyrusHaunt.Singleton, true);
I get error CS1503. How could I fix this?
Posts: 3,860
Thanks: 8537 in 67 Posts
I'm trying to make my custom haunt interaction appear to all ghost sims. However, the problem is that it is a solo interaction, and thus, it cannot be loaded the same way as others, apparently, I think it's because of this line of code:
Code:
new public static ISoloInteractionDefinition Singleton = new Definition(); Thus, when I try doing this on the instantiator class:
Code:
sim.AddInteraction(CyrusHaunt.Singleton, true); I get error CS1503. How could I fix this? |
sim.AddSoloInteractions(CyrusHaunt.Singleton);
Which I think will fix the Error as well. Else I assume it's because of the type the Definition is derived from. Make sure it's this:
public class Definition : SoloSimInteractionDefinition<CyrusHaunt>
Posts: 175
Thanks: 175 in 1 Posts
Here's the class:
public class Test { [Tunable] internal static bool kInstantiator; static Test() { World.sOnWorldLoadFinishedEventHandler = (EventHandler)Delegate.Combine(World.sOnWorldLoadFinishedEventHandler, new EventHandler(OnWorldFinishedLoading)); LoadSaveManager.ObjectGroupsPreLoad += OnPreLoad; } private static void OnWorldFinishedLoading(object sender, EventArgs e) { AlarmManager.Global.AddAlarm(1f, TimeUnit.Minutes, Start, "Start", AlarmType.NeverPersisted, null); EventTracker.AddListener(EventTypeId.kEventSimSelected, OnSelectedSimChanged); } public static void OnPreLoad() { new BuffBooter().LoadBuffData(); } private static void Start() { Sim[] objects = Sims3.Gameplay.Queries.GetObjects<Sim>(); foreach (Sim sim in objects) { if (sim != null && sim.IsHuman && !sim.IsRobot && !sim.IsEP11Bot) { sim.AddInteraction(PossessInteraction.Singleton, true); sim.AddInteraction(CyrusHaunt.Singleton, true); } } } public static ListenerAction OnSelectedSimChanged(Event e) { Sim[] sims = Sims3.Gameplay.Queries.GetObjects<Sim>(); foreach (Sim sim in sims) { Visibility.RefreshVisibility(sim.SimDescription, false); } return ListenerAction.Keep; }
Posts: 3,860
Thanks: 8537 in 67 Posts
I merged a few of your threads together that are about this specific interaction. Since it wasn't easy as the person helping what changed and how to help you with any questions. Plus! It makes it easier for you to track down what was going on.
But just know, it's fine to dedicate one thread to even a project, like Alunn does with their Yoga mod: https://modthesims.info/showthread.php?t=646330
It might be 4 pages long, but it's great stuff and information that's been given!
Also, not to sound mean here whatsoever, and I know that as a beginner it's easier to ask here since it's a sims-code-related issue, but getting errors like a CS1503 errors and such, is a great resource to learn about coding Or, in fact, learning to understand and read code. It's a hard thing to do at first, but it teaches your brain to read an error you have, you google it and StackOverflow has allll sorts of issues. But where the trick comes in (And teaching your brain with the logistics of coding, which is a skill altogether by itself) is to see what fixed things for them and how to apply something similar to your code. In fact, it even helps growing in programming to a degree where you find yourself writing most of the code yourself eventually, no matter which programmer language or thing you make it for (websites, games, apps). I do that all the time and that helped me tremendously when starting out sims coding and C#. So google first, if you really can't figure it out (which I totally get, I have that too occasionally and spend hours getting it to work lol) then of course it's cool to ask!
Hopefully, this doesn't sound like a personal attack or anything, I totally understand that it's hard to code and especially for Ts3! (Also a thank you can be lovely as well for the ones helping out )
But to get to your question:
Does nraas Errortrap give you any errors when the game loads? or Nraas traveler? because usually that indicates that there's some code it's not liking. What happens if you change the sOnWorldLoadFinishedEventHandler stuff into this instead:
World.sOnWorldLoadFinishedEventHandler += new EventHandler(OnWorldLoadFinished);
because else you're creating a whole new event handler and overriding the current one, which I don't think will work with other global mods.
Hope this helps a bit!
Posts: 175
Thanks: 175 in 1 Posts
Hey @CyrusBanefort ! I merged a few of your threads together that are about this specific interaction. Since it wasn't easy as the person helping what changed and how to help you with any questions. Plus! It makes it easier for you to track down what was going on. But just know, it's fine to dedicate one thread to even a project, like Alunn does with their Yoga mod: https://modthesims.info/showthread.php?t=646330 It might be 4 pages long, but it's great stuff and information that's been given! Also, not to sound mean here whatsoever, and I know that as a beginner it's easier to ask here since it's a sims-code-related issue, but getting errors like a CS1503 errors and such, is a great resource to learn about coding Or, in fact, learning to understand and read code. It's a hard thing to do at first, but it teaches your brain to read an error you have, you google it and StackOverflow has allll sorts of issues. But where the trick comes in (And teaching your brain with the logistics of coding, which is a skill altogether by itself) is to see what fixed things for them and how to apply something similar to your code. In fact, it even helps growing in programming to a degree where you find yourself writing most of the code yourself eventually, no matter which programmer language or thing you make it for (websites, games, apps). I do that all the time and that helped me tremendously when starting out sims coding and C#. So google first, if you really can't figure it out (which I totally get, I have that too occasionally and spend hours getting it to work lol) then of course it's cool to ask! Hopefully, this doesn't sound like a personal attack or anything, I totally understand that it's hard to code and especially for Ts3! (Also a thank you can be lovely as well for the ones helping out ) But to get to your question: Does nraas Errortrap give you any errors when the game loads? or Nraas traveler? because usually that indicates that there's some code it's not liking. What happens if you change the sOnWorldLoadFinishedEventHandler stuff into this instead:
Code:
World.sOnWorldLoadFinishedEventHandler += new EventHandler(OnWorldLoadFinished); because else you're creating a whole new event handler and overriding the current one, which I don't think will work with other global mods. Hope this helps a bit! |
Ah, sorry if I did not thank the people who helped. Somehow, my mind thought it would be better to not populate the thread with things not relevant to the topic, but I think it's fine now. Just thanking you for all the help 'till now. Well, I'll try doing this -- But I think there's some problem that goes deeper than that. I tried some solutions already, like making another class to put the instantiator on, but the problem persisted. There's not a error or anything, it just simply does not work. The buff even does not appear in MasterController's list. If I reckon correctly, errortrap did not tell me about anything in particular - Could be that I'm confusing myself, so I'll see about that. Perhaps this could be something related about having two instantiators in the same assembly? I'll also try creating a new assembly, adding it as a reference in this assembly and see if it will work.
Posts: 3,860
Thanks: 8537 in 67 Posts
Ah, sorry if I did not thank the people who helped. Somehow, my mind thought it would be better to not populate the thread with things not relevant to the topic, but I think it's fine now. Just thanking you for all the help 'till now. Well, I'll try doing this -- But I think there's some problem that goes deeper than that. I tried some solutions already, like making another class to put the instantiator on, but the problem persisted. There's not a error or anything, it just simply does not work. The buff even does not appear in MasterController's list. If I reckon correctly, errortrap did not tell me about anything in particular - Could be that I'm confusing myself, so I'll see about that. Perhaps this could be something related about having two instantiators in the same assembly? I'll also try creating a new assembly, adding it as a reference in this assembly and see if it will work. |
personally, Whenever it does this to me where things get unclickable and stuff, I usually refer back to this and start out clean again: http://www.simlogical.com/ContentUp..._script_mod.pdf
Posts: 175
Thanks: 175 in 1 Posts
Posts: 175
Thanks: 175 in 1 Posts
1: Making it so sims cannot autonomously start interactions with ghosts, to finish the visibility issue. (How could I do this? ITUNs, XMLs?
2: A idea that I got from the newest stuff pack in TS4 - A seance table that would allow for communing with otherwordly spirits and the summoning of them. Also, need ideas of what could be used to make this. Don't know if this could be possible.
We're almost there. Thanks for all the help I've got so far.
Posts: 3,860
Thanks: 8537 in 67 Posts
Okay, the mod is going smoothly. I have only two more systems to work into, excluding the reaction broadcaster for ghosts: 1: Making it so sims cannot autonomously start interactions with ghosts, to finish the visibility issue. (How could I do this? ITUNs, XMLs? |
2: A idea that I got from the newest stuff pack in TS4 - A seance table that would allow for communing with otherwordly spirits and the summoning of them. Also, need ideas of what could be used to make this. Don't know if this could be possible. |
Posts: 175
Thanks: 175 in 1 Posts
EDIT: So, I can't find out how to exactly only disallow the autonomy specifically to ghosts from the documentation, as I want the interactions to still be available to be user directed. What I can see is how to completely disallow the interaction for a certain occult.
Any idea what makes Imaginary Friends not interact autonomously with those who are not their owner?
EDIT2: Nevermind, I found it.
EDIT3: Ok, did my own version of the CanSocializeWith function.
public static class CanSocialize { public static bool CanSocializeWith(SimDescription targetDescription, Sim otherSim) { if (!targetDescription.IsGhost) { return true; } if (otherSim == null) { return true; } SimDescription simDescription = otherSim.SimDescription; if (simDescription == targetDescription) { return true; } if (simDescription != null && (simDescription.Occupation is GhostHunter || (simDescription.SkillManager.HasElement(SkillNames.Spellcraft) && simDescription.SkillManager.GetElement(SkillNames.Spellcraft).SkillLevel >= 5) || simDescription.CreatedSim.BuffManager.HasElement(0x15DABBECF72A9084))) { return true; } return false; } }
Just need to figure out how to instantiate it in the game. I tried doing this in the instantiator class:
foreach (Sim sim in sims) { Visibility.RefreshVisibility(sim.SimDescription, false); CanSocialize.CanSocializeWith(sim.SimDescription, false); }
Thought it would work, since the RefreshVisibility function is also a boolean, but it did not accept it.
EDIT4: Also tried doing this:
public static class CanSocialize { public static bool CanSocializeWith(Sim otherSim, bool immediate) { SimDescription simDescription = otherSim.SimDescription; if (simDescription.IsGhost) { return true; } if (otherSim == null) { return true; } if (simDescription == mSimDescription) { return true; } if (simDescription != null && (simDescription.Occupation is GhostHunter || (simDescription.SkillManager.HasElement(SkillNames.Spellcraft) && simDescription.SkillManager.GetElement(SkillNames.Spellcraft).SkillLevel >= 5) || simDescription.CreatedSim.BuffManager.HasElement(0x15DABBECF72A9084))) { return true; } return false; } public static SimDescription mSimDescription; }
It let me compile when I did this
CanSocialize.CanSocializeWith(sim, false);
However, nothing happened. The interactions continued to be autonomous. Also tried with only the sim otherSim argument, also to no avail. I'm starting to think that's not what makes the Imaginary Friend not interact with other sims.
EDIT5: Apparently, the code for making Imaginary Friends not interact with other sims is built into the interactions itself. So, I will need another plan.
Posts: 175
Thanks: 175 in 1 Posts
EDIT: Is it possible to add a listener that checks if the sim is trying to interact with another?
EDIT2: I found something that might be able to help me. I found a eventlistener called OnSocialization. My aim is to change these two pieces of code:
public static bool CanSimSocializeWithSim(Sim actor, Sim target) { OccultImaginaryFriend occult; if (TryGetOccultFromSim(actor, out occult) && !occult.CanSocializeWith(target)) { return false; } OccultImaginaryFriend occult2; if (TryGetOccultFromSim(target, out occult2) && !occult2.CanSocializeWith(actor)) { return false; } return true; }
and
public static bool TryGetOccultFromSim(Sim sim, out OccultImaginaryFriend occult) { if (sim != null && sim.SimDescription.IsImaginaryFriend) { occult = (sim.OccultManager.GetOccultType(OccultTypes.ImaginaryFriend) as OccultImaginaryFriend); return occult != null; } occult = null; return false; }
In something that could be used by ghosts, using the first boolean to cancel social interactions in case the sim isn't who I want to be, but I need help. I think if I finish these two interactions, the most difficult part of the mod is done, and I only need to focus on interactions.
Who Posted
|