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!
Quick Reply
Search this Thread
Test Subject
Original Poster
#1 Old 15th May 2024 at 11:07 PM
Default How does the EventLotMarker (uni) "know" when to switch between Layouts?
Hi all! Long time player / cc creator, new to modding and first time poster.

I'm looking for some assistance with understanding EA's EventLotMarker script - this is the object from Uni which controls changing the lot layout during the 'welcome' event. It add/removes objects associated with each layout type by the player depending on whether the 'welcome event' is happening or not. It's similar to the SeasonalLotMarker in that sense.

I'm trying to mimic some of the behaviour of this marker in scripting a new 'lot marker'. Essentially I'm copying wholesale the functionality of assigning build/buy objects to layouts, but I want to have 7 'events' for each day of the week, which occur at 18:00-02:00 daily, rather than the one-off event that uni has.

I've scoured the EventLotMarker script, and I believe I understand, and have recreated, all of the parts which relate to build/buy mode (the interactions which allow you to associate objects with each layout; preventing use of SeasonalLotMarker on the same lot). What I can't figure out is how that script identifies that the uni 'welcome event' is taking place in live mode and triggers the layout change there.

So in short, the question I can't figure out is, "How do I identify the part of the script which listens for the uni event, so that I can in my own script replace this with code which listens for the day of week and time of day, and use this to trigger adding/removing objects?"

I've had a look through Zerbu's Lot Events mod script for inspo, but that delivers me back to the same question, really - as from what I understand, Z didn't create a new marker, but instead the functionality to add extra events, which are then in turn identified by the original EventLotMarker. I still can't figure out how the EventLotMarker references these

I'd be really grateful for any pointers! The original EventLotMarker script from uni is as follows:

Code:
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Sims3.Gameplay;
using Sims3.Gameplay.Abstracts;
using Sims3.Gameplay.Actors;
using Sims3.Gameplay.Autonomy;
using Sims3.Gameplay.CAS;
using Sims3.Gameplay.Core;
using Sims3.Gameplay.Interactions;
using Sims3.Gameplay.Interfaces;
using Sims3.Gameplay.Objects;
using Sims3.Gameplay.Utilities;
using Sims3.Gameplay.WorldBuilderUtil;
using Sims3.SimIFace;
using Sims3.SimIFace.CustomContent;
using Sims3.UI;

public class EventLotMarker : GameObject, IBuildBuyListener, IHasWorldBuilderData
{
	public enum Layout : uint
	{
		Common,
		One,
		Two
	}

	private sealed class SetLayoutInteraction : ImmediateInteraction<Sim, EventLotMarker>
	{
		[DoesntRequireTuning]
		private sealed class Definition : ActorlessInteractionDefinition<Sim, EventLotMarker, SetLayoutInteraction>
		{
			public Layout Layout;

			[CompilerGenerated]
			private static GreyedOutTooltipCallback <>9__CachedAnonymousMethodDelegate1;

			public Definition()
			{
			}

			private Definition(Layout layout)
			{
				Layout = layout;
			}

			protected override bool Test(Sim actor, EventLotMarker target, bool isAutonomous, ref GreyedOutTooltipCallback greyedOutTooltipCallback)
			{
				if (target.mCurrentLayout == Layout)
				{
					greyedOutTooltipCallback = () => LocalizeString("AlreadySelectedTooltip");
					return false;
				}
				return true;
			}

			protected override string GetInteractionName(Sim actor, EventLotMarker target, InteractionObjectPair iop)
			{
				return LocalizeString(Layout.ToString());
			}

			protected override void AddInteractions(InteractionObjectPair iop, Sim actor, EventLotMarker target, List<InteractionObjectPair> results)
			{
				foreach (Layout value in Enum.GetValues(typeof(Layout)))
				{
					Definition interaction = new Definition(value);
					results.Add(new InteractionObjectPair(interaction, target));
				}
			}

			public override string[] GetPath(bool isFemale)
			{
				return new string[1] { LocalizeString("Path") };
			}
		}

		private const string sLocalizationKey = "Gameplay/Objects/GenericLotMarker/SetLayout";

		public static readonly InteractionDefinition Singleton = new Definition();

		private static string LocalizeString(string name, params object[] parameters)
		{
			return Localization.LocalizeString("Gameplay/Objects/GenericLotMarker/SetLayout:" + name, parameters);
		}

		protected override bool Run()
		{
			Target.SetLayout((base.InteractionDefinition as Definition).Layout, isBuildBuy: true);
			return true;
		}
	}

	private const string kWorldBuilderSystemName = "EventLotMarker";

	private const uint kEventListSizeHash = 1105684635u;

	private const uint kEventObjectIndexHash = 1923699495u;

	private const uint kEventDefaultLayoutHash = 2616623713u;

	[Tunable]
	[TunableComment("Transparency for common objects when set to a layout. If <=0.3f won't be able to pick")]
	private static float kCommonTransparancy = 0.31f;

	private Layout mCurrentLayout;

	private Dictionary<Layout, List<ObjectGuid>> mLayoutItems;

	private bool mIsBuildBuy;

	private bool mInitialUpdated;

	private ObjectGuid mLastObjectGrabbed = ObjectGuid.InvalidObjectGuid;

	public Layout CurrentSetup => mCurrentLayout;

	public override void OnCreation()
	{
		base.OnCreation();
		mLayoutItems = new Dictionary<Layout, List<ObjectGuid>>();
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			mLayoutItems[value] = new List<ObjectGuid>();
		}
	}

	public override void OnStartup()
	{
		base.OnStartup();
		if (Objects.IsValid(base.ObjectId))
		{
			SetFlags();
		}
	}

	public void SaveWorldBuilderData()
	{
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			WorldBuilderData.Set("EventLotMarker", base.ObjectId, value.ToString() + "Items", mLayoutItems[value], null);
		}
	}

	public void LoadWorldBuilderData()
	{
		foreach (Layout value2 in Enum.GetValues(typeof(Layout)))
		{
			List<ObjectGuid> value = new List<ObjectGuid>();
			WorldBuilderData.Get("EventLotMarker", base.ObjectId, value2.ToString() + "Items", ref value);
			if (value != null)
			{
				mLayoutItems[value2] = value;
			}
		}
		InitialUpdate();
	}

	public void InitialUpdate()
	{
		if (mInitialUpdated)
		{
			return;
		}
		mInitialUpdated = true;
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			if (value == Layout.Common)
			{
				continue;
			}
			foreach (ObjectGuid item in mLayoutItems[value])
			{
				GameObject @object = GameObject.GetObject<GameObject>(item);
				if (@object != null)
				{
					@object.AddToWorld();
					@object.RemoveFromWorld();
					World.SetFloorCutoutStateForObject(item, bEnable: false);
				}
			}
		}
		mCurrentLayout = Layout.Common;
	}

	private void SetFlags()
	{
		if (GameStates.IsBuildBuyLikeState)
		{
			SetHiddenFlags(HiddenFlags.Footprint);
		}
		else
		{
			SetHiddenFlags(HiddenFlags.Everything);
		}
	}

	private void ExportLayout(Layout currentLayout, IPropertyStreamWriter writer, ObjectIdTable objIdTable, uint index)
	{
		IPropertyStreamWriter propertyStreamWriter = writer.CreateChild(index);
		List<ObjectGuid> list = mLayoutItems[currentLayout];
		propertyStreamWriter.WriteInt32(1105684635u, list.Count);
		uint num = 0u;
		foreach (ObjectGuid item in list)
		{
			IPropertyStreamWriter propertyStreamWriter2 = propertyStreamWriter.CreateChild(num++);
			propertyStreamWriter2.WriteInt32(1923699495u, objIdTable.GetIndex(item));
			propertyStreamWriter.CommitChild();
		}
		writer.CommitChild();
	}

	public override bool ExportContent(ResKeyTable resKeyTable, ObjectIdTable objIdTable, IPropertyStreamWriter writer)
	{
		uint index = 0u;
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			if (value != 0)
			{
				ExportLayout(value, writer, objIdTable, index++);
			}
		}
		ExportLayout(Layout.Common, writer, objIdTable, index);
		writer.WriteInt16(2616623713u, (short)mCurrentLayout);
		return base.ExportContent(resKeyTable, objIdTable, writer);
	}

	private void ImportLayout(Layout currentLayout, IPropertyStreamReader reader, ObjectIdTable objIdTable, uint index)
	{
		IPropertyStreamReader child = reader.GetChild(index);
		if (child == null)
		{
			return;
		}
		List<ObjectGuid> list = mLayoutItems[currentLayout];
		child.ReadInt32(1105684635u, out var value, 0);
		uint num = 0u;
		while (num < value)
		{
			IPropertyStreamReader child2 = child.GetChild(num++);
			child2.ReadInt32(1923699495u, out var value2, -1);
			if (value2 != -1)
			{
				ObjectGuid item = objIdTable[value2];
				list.Add(item);
			}
		}
	}

	public override bool ImportContent(ResKeyTable resKeyTable, ObjectIdTable objIdTable, IPropertyStreamReader reader)
	{
		uint index = 0u;
		foreach (Layout value2 in Enum.GetValues(typeof(Layout)))
		{
			if (value2 != 0)
			{
				ImportLayout(value2, reader, objIdTable, index++);
			}
		}
		ImportLayout(Layout.Common, reader, objIdTable, index);
		reader.ReadInt16(2616623713u, out var value, 0);
		mCurrentLayout = (Layout)value;
		SetFlags();
		return base.ImportContent(resKeyTable, objIdTable, reader);
	}

	public void OnEnterBuildBuyMode()
	{
		UpdateVisualState();
		World.OnHandToolPickupCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolPickupCallback, new World.HandToolEventHandler(World_OnHandToolPickupCallback));
		World.OnHandToolPickupCallback = (World.HandToolEventHandler)Delegate.Combine(World.OnHandToolPickupCallback, new World.HandToolEventHandler(World_OnHandToolPickupCallback));
		World.OnHandToolEditCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolEditCallback, new World.HandToolEventHandler(World_OnHandToolEditCallback));
		World.OnHandToolEditCallback = (World.HandToolEventHandler)Delegate.Combine(World.OnHandToolEditCallback, new World.HandToolEventHandler(World_OnHandToolEditCallback));
		World.OnHandToolSoldCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolSoldCallback, new World.HandToolEventHandler(World_OnHandToolSoldCallback));
		World.OnHandToolSoldCallback = (World.HandToolEventHandler)Delegate.Combine(World.OnHandToolSoldCallback, new World.HandToolEventHandler(World_OnHandToolSoldCallback));
		Household household = LotManager.ActiveLot.Household;
		if (household != null && household.SharedFamilyInventory != null && household.SharedFamilyInventory.Inventory != null)
		{
			Inventory inventory = household.SharedFamilyInventory.Inventory;
			inventory.EventCallback = (InventoryEventCallback)Delegate.Remove(inventory.EventCallback, new InventoryEventCallback(Inventory_EventCallback));
			Inventory inventory2 = household.SharedFamilyInventory.Inventory;
			inventory2.EventCallback = (InventoryEventCallback)Delegate.Combine(inventory2.EventCallback, new InventoryEventCallback(Inventory_EventCallback));
		}
	}

	public void OnExitBuildBuyMode()
	{
		UpdateVisualState();
		World.OnHandToolPickupCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolPickupCallback, new World.HandToolEventHandler(World_OnHandToolPickupCallback));
		World.OnHandToolEditCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolEditCallback, new World.HandToolEventHandler(World_OnHandToolEditCallback));
		World.OnHandToolSoldCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolSoldCallback, new World.HandToolEventHandler(World_OnHandToolSoldCallback));
		Household household = base.LotCurrent.Household;
		if (household != null && household.SharedFamilyInventory != null && household.SharedFamilyInventory.Inventory != null)
		{
			Inventory inventory = household.SharedFamilyInventory.Inventory;
			inventory.EventCallback = (InventoryEventCallback)Delegate.Remove(inventory.EventCallback, new InventoryEventCallback(Inventory_EventCallback));
		}
	}

	private void World_OnHandToolPickupCallback(object sender, World.HandToolEventArgs eventArgs)
	{
		World.HandToolPickupEventArgs handToolPickupEventArgs = (World.HandToolPickupEventArgs)eventArgs;
		switch (handToolPickupEventArgs.PickupType)
		{
		case ePickupTypeHandTool.kPickupTypeCreated:
		case ePickupTypeHandTool.kPickupTypeCreatedDuplicate:
			mLastObjectGrabbed = ObjectGuid.InvalidObjectGuid;
			SetToLayout(handToolPickupEventArgs.ObjectId, cleanLayout: false);
			break;
		case ePickupTypeHandTool.kPickupTypeGrabbed:
			if (!mLayoutItems[mCurrentLayout].Contains(handToolPickupEventArgs.ObjectId))
			{
				mLastObjectGrabbed = handToolPickupEventArgs.ObjectId;
			}
			SetToLayout(handToolPickupEventArgs.ObjectId, cleanLayout: false);
			break;
		}
	}

	private void World_OnHandToolEditCallback(object sender, World.HandToolEventArgs eventArgs)
	{
		World.HandToolEditEventArgs handToolEditEventArgs = (World.HandToolEditEventArgs)eventArgs;
		switch (handToolEditEventArgs.EditType)
		{
		case World.eEditTypeHandTool.kEditTypePlaced:
			mLastObjectGrabbed = ObjectGuid.InvalidObjectGuid;
			SetToLayout(handToolEditEventArgs.ObjectId, cleanLayout: false);
			break;
		case World.eEditTypeHandTool.kEditTypeCancelled:
			if (mLastObjectGrabbed != ObjectGuid.InvalidObjectGuid)
			{
				SetToLayout(mLastObjectGrabbed, cleanLayout: false, Layout.Common);
			}
			mLastObjectGrabbed = ObjectGuid.InvalidObjectGuid;
			break;
		case World.eEditTypeHandTool.kEditTypeDeleted:
			mLastObjectGrabbed = ObjectGuid.InvalidObjectGuid;
			SetToLayout(handToolEditEventArgs.ObjectId, cleanLayout: true);
			break;
		default:
			mLastObjectGrabbed = ObjectGuid.InvalidObjectGuid;
			break;
		case World.eEditTypeHandTool.kEditTypeUndoPlaced:
			break;
		}
	}

	private void World_OnHandToolSoldCallback(object sender, World.HandToolEventArgs eventArgs)
	{
		SetToLayout(eventArgs.ObjectId, cleanLayout: true);
	}

	private void Inventory_EventCallback(uint stackNumber, InventoryEvent inventoryEvent, IGameObject iobj)
	{
		GameObject gameObject = (GameObject)iobj;
		switch (inventoryEvent)
		{
		case InventoryEvent.kStackAddedTo:
		case InventoryEvent.kStackCreated:
			SetToLayout(gameObject.ObjectId, cleanLayout: true);
			break;
		case InventoryEvent.kStackRemovedFrom:
		case InventoryEvent.kStackDeleted:
			break;
		}
	}

	public override void OnHandToolPlacement()
	{
		OnEnterBuildBuyMode();
	}

	protected override void AddBuildBuyInteractions(List<InteractionDefinition> buildBuyInteractions)
	{
		base.AddBuildBuyInteractions(buildBuyInteractions);
		buildBuyInteractions.Add(SetLayoutInteraction.Singleton);
	}

	public override void Dispose()
	{
		Clear();
		base.Dispose();
	}

	public override void Destroy()
	{
		Clear();
		base.Destroy();
	}

	public override bool HandToolAllowPlacement(ref string errorStr)
	{
		Lot activeLot = LotManager.ActiveLot;
		if (activeLot != null)
		{
			EventLotMarker[] objects = activeLot.GetObjects<EventLotMarker>();
			SeasonalLotMarker[] objects2 = activeLot.GetObjects<SeasonalLotMarker>();
			if ((objects.Length > 0 && objects[0] != this) || objects2.Length > 0)
			{
				errorStr = Localization.LocalizeString("Gameplay/Objects/SeasonalLotMarker:OneOnly");
				return false;
			}
		}
		return base.HandToolAllowPlacement(ref errorStr);
	}

	public void UpdateLayout(Layout layout)
	{
		SetLayout(layout, isBuildBuy: false);
	}

	private void Clear()
	{
		World.OnHandToolPickupCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolPickupCallback, new World.HandToolEventHandler(World_OnHandToolPickupCallback));
		World.OnHandToolEditCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolEditCallback, new World.HandToolEventHandler(World_OnHandToolEditCallback));
		World.OnHandToolSoldCallback = (World.HandToolEventHandler)Delegate.Remove(World.OnHandToolSoldCallback, new World.HandToolEventHandler(World_OnHandToolSoldCallback));
		Lot lot = base.LotCurrent;
		if (GameStates.IsBuildBuyLikeState)
		{
			lot = LotManager.ActiveLot;
		}
		if (lot == null)
		{
			return;
		}
		Household household = lot.Household;
		if (household != null && household.SharedFamilyInventory != null && household.SharedFamilyInventory.Inventory != null)
		{
			Inventory inventory = household.SharedFamilyInventory.Inventory;
			inventory.EventCallback = (InventoryEventCallback)Delegate.Remove(inventory.EventCallback, new InventoryEventCallback(Inventory_EventCallback));
		}
		GameObject[] objects = lot.GetObjects<GameObject>();
		foreach (GameObject gameObject in objects)
		{
			if (gameObject is Sim || gameObject == this || !gameObject.InWorld || (gameObject.GetHiddenFlags() & HiddenFlags.Model) == HiddenFlags.Model)
			{
				continue;
			}
			bool flag = false;
			foreach (Layout value in Enum.GetValues(typeof(Layout)))
			{
				if (value != 0 && mLayoutItems[value].Contains(gameObject.ObjectId))
				{
					flag = true;
				}
			}
			if (!flag)
			{
				gameObject.SetOpacity(1f, 0f);
			}
		}
		foreach (Layout value2 in Enum.GetValues(typeof(Layout)))
		{
			if (value2 == Layout.Common || mCurrentLayout == value2)
			{
				continue;
			}
			foreach (ObjectGuid item in mLayoutItems[value2])
			{
				GameObject @object = GameObject.GetObject<GameObject>(item);
				if (@object != null)
				{
					@object.AddToWorld();
				}
				else
				{
					World.ObjectSetHiddenFlags(item, 0u);
				}
			}
		}
	}

	private void UpdateVisualState()
	{
		if (GameStates.NextInWorldStateId == InWorldState.SubState.BuildMode || GameStates.NextInWorldStateId == InWorldState.SubState.BuyMode)
		{
			UpdateVisibilityForBuildBuy();
		}
		else
		{
			SetHiddenFlags(HiddenFlags.Everything);
		}
	}

	private void UpdateVisibilityForBuildBuy()
	{
		if (!BuyController.IsBuyDebugEnabled())
		{
			SetHiddenFlags(HiddenFlags.Everything);
		}
		else
		{
			SetHiddenFlags(HiddenFlags.Footprint);
		}
	}

	private void SetToLayout(ObjectGuid objectId, bool cleanLayout)
	{
		SetToLayout(objectId, cleanLayout, mCurrentLayout);
	}

	private void SetToLayout(ObjectGuid objectId, bool cleanLayout, Layout setLayout)
	{
		GameObject @object = GameObject.GetObject<GameObject>(objectId);
		if (@object is IMailbox || @object is EventLotMarker || @object is IPostBox || @object is IResidentialTrashCan || @object is IFlora || @object is RoomMarker || @object is TombRoomMarker)
		{
			return;
		}
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			mLayoutItems[value].Remove(objectId);
		}
		if (setLayout == Layout.Common || cleanLayout)
		{
			if (@object != null)
			{
				if (!cleanLayout)
				{
					@object.AddToWorld();
					mLayoutItems[setLayout].Add(objectId);
				}
				if (setLayout == mCurrentLayout)
				{
					@object.SetOpacity(1f, 0f);
				}
				else
				{
					@object.SetOpacity(kCommonTransparancy, 0f);
				}
			}
			else if (!cleanLayout)
			{
				World.ObjectSetHiddenFlags(objectId, 0u);
				mLayoutItems[setLayout].Add(objectId);
			}
			return;
		}
		@object?.SetOpacity(1f, 0f);
		mLayoutItems[setLayout].Add(objectId);
		Slot[] containmentSlotNames = Slots.GetContainmentSlotNames(objectId);
		Slot[] array = containmentSlotNames;
		foreach (Slot slotNameHash in array)
		{
			ObjectGuid containedObject = Slots.GetContainedObject(objectId, (uint)slotNameHash);
			if (containedObject != ObjectGuid.InvalidObjectGuid)
			{
				SetToLayout(containedObject, cleanLayout: false, setLayout);
			}
		}
	}

	public bool IsLayoutItem(ObjectGuid objectId)
	{
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			if (mLayoutItems[value].Contains(objectId))
			{
				return true;
			}
		}
		return false;
	}

	private void SetLayout(Layout newLayout, bool isBuildBuy)
	{
		bool flag = isBuildBuy && newLayout != Layout.Common;
		bool flag2 = Simulator.CheckYieldingContext(shouldThrowException: false);
		Lot lot = base.LotCurrent;
		if (isBuildBuy)
		{
			lot = LotManager.ActiveLot;
		}
		if (lot == null)
		{
			return;
		}
		GameObject[] objects = lot.GetObjects<GameObject>();
		foreach (GameObject gameObject in objects)
		{
			if (gameObject is Sim || gameObject == this || !gameObject.InWorld || (gameObject.GetHiddenFlags() & HiddenFlags.Model) == HiddenFlags.Model)
			{
				continue;
			}
			bool flag3 = false;
			foreach (Layout value in Enum.GetValues(typeof(Layout)))
			{
				if (value != 0 && mLayoutItems[value].Contains(gameObject.ObjectId))
				{
					flag3 = true;
					break;
				}
			}
			if (!flag3)
			{
				if (flag)
				{
					gameObject.SetOpacity(kCommonTransparancy, 0f);
				}
				else
				{
					gameObject.SetOpacity(1f, 0f);
				}
			}
		}
		bool flag4 = false;
		if (mCurrentLayout != newLayout)
		{
			if (flag2)
			{
				if (mCurrentLayout != 0)
				{
					foreach (ObjectGuid item in mLayoutItems[mCurrentLayout])
					{
						GameObject @object = GameObject.GetObject<GameObject>(item);
						if (@object != null)
						{
							@object.SetObjectToReset();
							flag4 = true;
						}
					}
				}
				List<GameObject> list = new List<GameObject>();
				if (!isBuildBuy)
				{
					GameObject[] objects2 = lot.GetObjects<GameObject>();
					GameObject[] array = objects2;
					foreach (GameObject gameObject2 in array)
					{
						if (!(gameObject2 is IDoNotMoveInEditTown))
						{
							Lot ownerLot = gameObject2.GetOwnerLot();
							if (ownerLot != null && ownerLot != lot && ownerLot.Household != null && ownerLot.Household.SharedFamilyInventory != null)
							{
								gameObject2.SetObjectToReset();
								list.Add(gameObject2);
								flag4 = true;
							}
						}
					}
				}
				if (flag4)
				{
					Simulator.Sleep(0u);
					Simulator.Sleep(0u);
					flag4 = false;
				}
				foreach (GameObject item2 in list)
				{
					Lot ownerLot2 = item2.GetOwnerLot();
					ownerLot2.Household.SharedFamilyInventory.Inventory.TryToAdd(item2);
				}
			}
			if (mCurrentLayout != 0)
			{
				foreach (ObjectGuid item3 in mLayoutItems[mCurrentLayout])
				{
					GameObject object2 = GameObject.GetObject<GameObject>(item3);
					if (object2 != null)
					{
						object2.RemoveFromWorld();
						World.SetFloorCutoutStateForObject(item3, bEnable: false);
					}
					else
					{
						World.ObjectSetHiddenFlags(item3, uint.MaxValue);
					}
				}
			}
		}
		mCurrentLayout = newLayout;
		mIsBuildBuy = isBuildBuy;
		Dictionary<GameObject, bool> dictionary = new Dictionary<GameObject, bool>();
		if (mCurrentLayout != 0)
		{
			foreach (ObjectGuid item4 in mLayoutItems[mCurrentLayout])
			{
				GameObject object3 = GameObject.GetObject<GameObject>(item4);
				if (object3 != null)
				{
					object3.AddToWorld();
					World.SetFloorCutoutStateForObject(item4, bEnable: true);
				}
				else
				{
					World.ObjectSetHiddenFlags(item4, 0u);
				}
				if (isBuildBuy)
				{
					continue;
				}
				GameObject[] objectsIntersectingObject = Sims3.Gameplay.Queries.GetObjectsIntersectingObject(item4);
				if (objectsIntersectingObject == null)
				{
					continue;
				}
				GameObject[] array2 = objectsIntersectingObject;
				foreach (GameObject gameObject3 in array2)
				{
					if (dictionary.ContainsKey(gameObject3) || !gameObject3.InWorld || IsLayoutItem(gameObject3.ObjectId) || gameObject3 is IFlora)
					{
						continue;
					}
					if (object3 != null)
					{
						if (object3.Parent != gameObject3 && gameObject3.Parent != object3)
						{
							dictionary.Add(gameObject3, value: true);
						}
					}
					else
					{
						dictionary.Add(gameObject3, value: true);
					}
				}
			}
		}
		foreach (GameObject key in dictionary.Keys)
		{
			key.SetObjectToReset();
			flag4 = flag2;
		}
		if (flag4)
		{
			flag4 = false;
			Simulator.Sleep(0u);
			Simulator.Sleep(0u);
		}
		foreach (GameObject key2 in dictionary.Keys)
		{
			Vector3 position = key2.Position;
			Vector3 forward = key2.ForwardVector;
			if (!GlobalFunctions.FindGoodLocationNearby(key2, ref position, ref forward))
			{
				if (key2 is Sim sim)
				{
					sim.AttemptToPutInSafeLocation(sendHome: false);
				}
				else
				{
					key2.Destroy();
				}
			}
			else
			{
				key2.SetPosition(position);
				key2.SetForward(forward);
			}
		}
		if (isBuildBuy)
		{
			return;
		}
		Household activeHousehold = Household.ActiveHousehold;
		if (activeHousehold != null)
		{
			foreach (Sim sim2 in activeHousehold.Sims)
			{
				if (sim2.MapTagManager != null && sim2.IsHuman)
				{
					sim2.MapTagManager.RefreshTag(lot);
				}
			}
		}
		World.LotSnowUpdate(lot.LotId);
		if ((lot.IsCommunityLot || !lot.IsActive) && Simulator.CheckYieldingContext(shouldThrowException: false))
		{
			World.RegenImposter(lot.LotId);
			World.SetImposterMode(enable: false);
		}
	}

	public void Replace(GameObject oldObject, GameObject newObject)
	{
		bool flag = true;
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			List<ObjectGuid> list = mLayoutItems[value];
			if (list.Contains(oldObject.ObjectId))
			{
				list.Remove(oldObject.ObjectId);
				list.Add(newObject.ObjectId);
				flag = value == Layout.Common;
				break;
			}
		}
		if (flag && mCurrentLayout != 0 && GameStates.IsBuildBuyLikeState)
		{
			newObject.SetOpacity(kCommonTransparancy, 0f);
			oldObject.SetOpacity(1f, 0f);
		}
	}

	public void Remove(ObjectGuid objectId)
	{
		foreach (Layout value in Enum.GetValues(typeof(Layout)))
		{
			if (value != 0)
			{
				List<ObjectGuid> list = mLayoutItems[value];
				if (list.Contains(objectId))
				{
					list.Remove(objectId);
				}
			}
		}
	}

	public static bool SameLayout(IGameObject gameObjectA, IGameObject gameObjectB)
	{
		if (gameObjectA.LotCurrent != null)
		{
			EventLotMarker[] objects = gameObjectA.LotCurrent.GetObjects<EventLotMarker>();
			if (objects.Length > 0)
			{
				foreach (Layout value in Enum.GetValues(typeof(Layout)))
				{
					List<ObjectGuid> list = objects[0].mLayoutItems[value];
					if (list.Contains(gameObjectA.ObjectId))
					{
						if (list.Contains(gameObjectB.ObjectId))
						{
							return true;
						}
						return false;
					}
					if (list.Contains(gameObjectB.ObjectId))
					{
						return false;
					}
				}
			}
		}
		return true;
	}
}

Advertisement
Instructor
#2 Old 16th May 2024 at 1:59 AM
The EventLotMarker doesn't itself reference the orientation situation, because it's meant to be used in a more generic way like how Zerbu implemented it.

When the OrientationSituation begins (see Sims3.Gameplay.Situations.OrientationSituations.ScheduleTodaysOrientation()), it finds the marker on the student union lot and calls its UpdateLayout() method, which accepts as an argument the layout type you want to switch to (the orientation uses "One"). After orientation ends, UpdateLayout() is called again with the "Common" layout.

So if you wanted to use a marker like this to change layouts at a set time every day, just make a repeating alarm and include a call to UpdateLayout() in the callback.

"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
Test Subject
Original Poster
#3 Old 17th May 2024 at 1:56 PM
Quote: Originally posted by gamefreak130
The EventLotMarker doesn't itself reference the orientation situation, because it's meant to be used in a more generic way like how Zerbu implemented it.

When the OrientationSituation begins (see Sims3.Gameplay.Situations.OrientationSituations.ScheduleTodaysOrientation()), it finds the marker on the student union lot and calls its UpdateLayout() method, which accepts as an argument the layout type you want to switch to (the orientation uses "One"). After orientation ends, UpdateLayout() is called again with the "Common" layout.

So if you wanted to use a marker like this to change layouts at a set time every day, just make a repeating alarm and include a call to UpdateLayout() in the callback.


Ah brilliant, thank you so much for your help! I'll give this a go.
Back to top