public override bool Verify(VM vm, VMAvatar caller) { //since architecture commands must be run in order, we need to run all architecture commands synchronously. //it must be queued on the global link. if (Verified) { return(true); } if (!vm.TS1 && (caller == null || //caller must be on lot, have build permissions caller.AvatarState.Permissions < VMTSOAvatarPermissions.BuildBuyRoommate)) { return(false); } for (int i = 0; i < Commands.Count; i++) { var cmd = Commands[i]; cmd.CallerUID = ActorUID; Commands[i] = cmd; } vm.GlobalLink.QueueArchitecture(this); return(false); }
public void Save(VMAvatar avatar) { SkinTone = (byte)avatar.SkinTone; DefaultSuits = avatar.DefaultSuits; //todo: clone? //if naked or using clothes rack, save in daywear. //TODO: store and check simantics outfit category, and restore using that instead. var dyn = avatar.DynamicSuits; var bID = avatar.BodyOutfit.ID; var saveDaywear = dyn.Daywear == bID || dyn.Sleepwear == bID || dyn.Swimwear == bID; saveDaywear = saveDaywear || (bID == 0x24E0000000D || bID == 0x10000000D); BodyOutfit = (saveDaywear)?avatar.DefaultSuits.Daywear.ID : bID; HeadOutfit = avatar.HeadOutfit.ID; Name = avatar.Name; Permissions = avatar.AvatarState.Permissions; AvatarFlags = ((VMTSOAvatarState)avatar.TSOState).Flags; Budget = avatar.TSOState.Budget.Value; for (int i = 0; i < MotiveData.Length; i++) { MotiveData[i] = avatar.GetMotiveData((VMMotive)i); } MotiveData[(int)(VMMotive.SleepState)] = 0; for (int i = 0; i < PersonDataMap.Length; i++) { PersonData[i] = avatar.GetPersonData((VMPersonDataVariable)PersonDataMap[i]); } SkillLock = avatar.SkillLocks; OnlineJobInfo = ((VMTSOAvatarState)avatar.TSOState).JobInfo; IgnoredAvatars = ((VMTSOAvatarState)avatar.TSOState).IgnoredAvatars; }
public void Apply(VMAvatar avatar) { avatar.SkinTone = (AppearanceType)SkinTone; for (int i = 0; i < PersonDataMap.Length; i++) { avatar.ForceEnableSkill = true; avatar.SetPersonData((VMPersonDataVariable)PersonDataMap[i], PersonData[i]); avatar.ForceEnableSkill = false; } avatar.SetPersonData(VMPersonDataVariable.SkinColor, SkinTone); avatar.DefaultSuits = DefaultSuits; avatar.BodyOutfit = new VMOutfitReference(BodyOutfit); avatar.HeadOutfit = new VMOutfitReference(HeadOutfit); avatar.Name = Name; avatar.AvatarState.Permissions = Permissions; ((VMTSOAvatarState)avatar.TSOState).Flags = AvatarFlags; avatar.TSOState.Budget.Value = Budget; avatar.PersistID = PersistID; avatar.ReplaceMotiveData(MotiveData); avatar.MeToPersist = new Dictionary <uint, List <short> >(); foreach (var obj in Relationships) { avatar.MeToPersist[obj.Target] = new List <short>(obj.Values); } ((VMTSOAvatarState)avatar.TSOState).JobInfo = OnlineJobInfo; if (IsWorker) { avatar.SetPersonData(VMPersonDataVariable.OnlineJobStatusFlags, 1); //validated immediately. } avatar.SkillLocks = SkillLock; ((VMTSOAvatarState)avatar.TSOState).IgnoredAvatars = IgnoredAvatars; }
public override bool Execute(VM vm, VMAvatar caller) { if (ResponseText.Length > 1024) { ResponseText = ResponseText.Substring(0, 1024); } VMEntity owner = caller; if (vm.TS1) { owner = vm.GlobalBlockingDialog; vm.SpeedMultiplier = vm.LastSpeedMultiplier; vm.LastSpeedMultiplier = 0; vm.GlobalBlockingDialog = null; } if (owner == null || owner.Thread.BlockingState == null || !(owner.Thread.BlockingState is VMDialogResult)) { return(false); } var state = (VMDialogResult)owner.Thread.BlockingState; state.Responded = true; state.ResponseCode = ResponseCode; state.ResponseText = ResponseText; return(true); }
private Animation PlayAnim(string name, VMAvatar avatar) { var animation = TSO.Content.Content.Get().AvatarAnimations.Get(name + ".anim"); avatar.CurrentAnimation = animation; avatar.CurrentAnimationState = new VMAnimationState(); avatar.Avatar.LeftHandGesture = SimHandGesture.Idle; avatar.Avatar.RightHandGesture = SimHandGesture.Idle; foreach (var motion in animation.Motions) { if (motion.TimeProperties == null) { continue; } foreach (var tp in motion.TimeProperties) { foreach (var item in tp.Items) { avatar.CurrentAnimationState.TimePropertyLists.Add(item); } } } /** Sort time property lists by time **/ avatar.CurrentAnimationState.TimePropertyLists.Sort(new TimePropertyListItemSorter()); return(animation); }
public static short SetSuit(VMAvatar avatar, short outfitType, short newIndex) { var validSuits = GetValidOutfits(avatar, outfitType); var bodyStrings = avatar.Object.Resource.Get <FSO.Files.Formats.IFF.Chunks.STR>(avatar.Object.OBJ.BodyStringID); var bsInd = OutfitTypeToInd[outfitType]; var oldSuit = bodyStrings.GetString(bsInd).Split(';')[0]; var prevInd = Array.FindIndex(validSuits, x => x.Item1.ToLowerInvariant() == bodyStrings.GetString(bsInd).Split(';')[0].ToLowerInvariant()); var newSuit = validSuits[newIndex]; bodyStrings.SetString(bsInd, newSuit.Item1, STRLangCode.EnglishUS); if (outfitType == 0 && newSuit.Item2 != "") { //right now only replace the handgroup when changing the default outfit. var hg = newSuit.Item2; bodyStrings.SetString(17, TilEQ(bodyStrings.GetString(17, STRLangCode.EnglishUS)) + "huao" + hg, STRLangCode.EnglishUS); bodyStrings.SetString(18, TilEQ(bodyStrings.GetString(18, STRLangCode.EnglishUS)) + "huao" + hg, STRLangCode.EnglishUS); bodyStrings.SetString(19, TilEQ(bodyStrings.GetString(19, STRLangCode.EnglishUS)) + "huap" + hg, STRLangCode.EnglishUS); bodyStrings.SetString(20, TilEQ(bodyStrings.GetString(20, STRLangCode.EnglishUS)) + "huap" + hg, STRLangCode.EnglishUS); bodyStrings.SetString(21, TilEQ(bodyStrings.GetString(21, STRLangCode.EnglishUS)) + "huac" + hg, STRLangCode.EnglishUS); bodyStrings.SetString(22, TilEQ(bodyStrings.GetString(22, STRLangCode.EnglishUS)) + "huac" + hg, STRLangCode.EnglishUS); } Content.GameContent.Get.Neighborhood.AvatarChanged(avatar.Object.OBJ.GUID); return((short)prevInd); }
public override bool Execute(VM vm, VMAvatar caller) { //need caller to be present if (caller == null) { return(false); } var limit = caller.SkillLocks; SkillID = Math.Min(SkillID, (byte)5); //must be 0-5 int otherLocked = 0; for (int i = 0; i < 6; i++) //sum other skill locks to see what we can feasibly put in this skill { if (i == SkillID) { continue; } otherLocked += caller.GetPersonData((VMPersonDataVariable)((int)VMPersonDataVariable.SkillLockBase + i)) / 100; } if (otherLocked >= limit) { return(false); //cannot lock this skill at all } LockLevel = (short)Math.Min(caller.GetPersonData(LockToSkill[SkillID]) / 100, Math.Min(LockLevel, (short)(limit - otherLocked))); //can only lock up to the limit caller.SetPersonData((VMPersonDataVariable)((int)VMPersonDataVariable.SkillLockBase + SkillID), (short)(LockLevel * 100)); return(true); }
public override bool Execute(VM vm, VMAvatar caller) { //switch this client's controlled sim to another //only used for TS1. //not suitable for networking right now. If you want to do anything weird with ts1 multiplayer, needs these additions: // - block stealing sims controlled by others // - block assuming control of npcs (this is enforced by simitone ui) // - multiplayer handling of "selected sim" global var target = vm.GetObjectById(TargetID); if (target == null || target is VMGameObject) { return(false); } if (caller != null && caller.PersistID == ActorUID) { //relinquish previous control vm.Context.ObjectQueries.RemoveAvatarPersist(caller.PersistID); caller.PersistID = 0; } target.PersistID = ActorUID; vm.Context.ObjectQueries.RegisterAvatarPersist((VMAvatar)target, target.PersistID); vm.SetGlobalValue(3, target.ObjectID); if (VM.UseWorld) { vm.Context.World.CenterTo(target.WorldUI); } return(true); }
public void RegisterAvatarPersist(VMAvatar ava, uint persistID) { if (persistID != 0) { AvatarsByPersist[persistID] = ava; } }
public void Tick(VMAvatar avatar) { Ticked = true; if (PerHourChange != 0) { double rate = (PerHourChange / 60.0) / (30.0 * 5.0); //timed for 5 second minutes fractional += rate; if (Math.Abs(fractional) >= 1) { var motive = avatar.GetMotiveData(Motive); if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { return; } //we're already over, do nothing. (do NOT clamp) motive += (short)(fractional); fractional %= 1.0; if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { motive = MaxValue; } //DO NOT CLEAR MOTIVE WHEN IT HITS MAX VALUE! fixes pet, maybe shower. avatar.SetMotiveData(Motive, motive); } } }
public override bool Execute(VM vm) { var sim = vm.Context.CreateObjectInstance(VMAvatar.TEMPLATE_PERSON, LotTilePos.OUT_OF_WORLD, Direction.NORTH).Objects[0]; var mailbox = vm.Entities.FirstOrDefault(x => (x.Object.OBJ.GUID == 0xEF121974 || x.Object.OBJ.GUID == 0x1D95C9B0)); if (VM.UseWorld) { FSO.HIT.HITVM.Get().PlaySoundEvent("lot_enter"); } if (mailbox != null) { VMFindLocationFor.FindLocationFor(sim, mailbox, vm.Context); } sim.PersistID = SimID; VMAvatar avatar = (VMAvatar)sim; avatar.SkinTone = (Vitaboy.AppearanceType)SkinTone; avatar.SetPersonData(VMPersonDataVariable.Gender, (short)((Gender) ? 1 : 0)); avatar.DefaultSuits = new VMAvatarDefaultSuits(Gender); avatar.DefaultSuits.Daywear = BodyID; avatar.BodyOutfit = BodyID; avatar.HeadOutfit = HeadID; avatar.Name = Name; vm.SignalChatEvent(new VMChatEvent(avatar.PersistID, VMChatEventType.Join, avatar.Name)); return(true); }
/// <summary> /// Called on server when someone requests to place an object from inventory. /// Immediately "fails" verification to be queued later, once the data has been retrieved. /// </summary> /// <param name="vm"></param> /// <param name="caller"></param> /// <returns></returns> public override bool Verify(VM vm, VMAvatar caller) { if (Verified) { return(true); //set internally when transaction succeeds. trust that the verification happened. } if (caller == null || //caller must be on lot, be a roommate. ((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Roommate || !vm.TSOState.CanPlaceNewUserObject(vm)) { return(false); } vm.GlobalLink.RetrieveFromInventory(vm, ObjectPID, caller.PersistID, (uint guid, byte[] data) => { if (guid == 0) { return; //todo: error feedback? } GUID = guid; Data = data; Verified = true; vm.ForwardCommand(this); }); return(false); }
public static ulong GetValue(VMAvatar avatar, VMPersonSuits type) { switch (type) { case VMPersonSuits.DefaultDaywear: return(avatar.DefaultSuits.Daywear.ID); case VMPersonSuits.DefaultSleepwear: return(avatar.DefaultSuits.Sleepwear.ID); case VMPersonSuits.DefaultSwimwear: return(avatar.DefaultSuits.Swimwear.ID); case VMPersonSuits.DynamicCostume: return(avatar.DynamicSuits.Costume); case VMPersonSuits.DynamicDaywear: return(avatar.DynamicSuits.Daywear); case VMPersonSuits.DynamicSleepwear: return(avatar.DynamicSuits.Sleepwear); case VMPersonSuits.DynamicSwimwear: return(avatar.DynamicSuits.Swimwear); } return(0); }
public void Save(VMAvatar avatar) { SkinTone = (byte)avatar.SkinTone; DefaultSuits = avatar.DefaultSuits; //todo: clone? //if naked, save in daywear. BodyOutfit = (avatar.BodyOutfit.ID == 0x24E0000000D || avatar.BodyOutfit.ID == 0x10000000D)?avatar.DefaultSuits.Daywear.ID : avatar.BodyOutfit.ID; HeadOutfit = avatar.HeadOutfit.ID; Name = avatar.Name; Permissions = ((VMTSOAvatarState)avatar.TSOState).Permissions; AvatarFlags = ((VMTSOAvatarState)avatar.TSOState).Flags; Budget = avatar.TSOState.Budget.Value; for (int i = 0; i < MotiveData.Length; i++) { MotiveData[i] = avatar.GetMotiveData((VMMotive)i); } MotiveData[(int)(VMMotive.SleepState)] = 0; for (int i = 0; i < PersonDataMap.Length; i++) { PersonData[i] = avatar.GetPersonData((VMPersonDataVariable)PersonDataMap[i]); } SkillLock = avatar.SkillLocks; OnlineJobInfo = ((VMTSOAvatarState)avatar.TSOState).JobInfo; IgnoredAvatars = ((VMTSOAvatarState)avatar.TSOState).IgnoredAvatars; }
/// <summary> /// Called on server when someone requests to place an object from inventory. /// Immediately "fails" verification to be queued later, once the data has been retrieved. /// </summary> /// <param name="vm"></param> /// <param name="caller"></param> /// <returns></returns> public override bool Verify(VM vm, VMAvatar caller) { if (Verified) { return(true); //set internally when transaction succeeds. trust that the verification happened. } //typically null caller, non-roommate cause failure. some lot specific things may apply. Mode = vm.PlatformState.Validator.GetPurchaseMode(Mode, caller, 0, true); if (Mode == PurchaseMode.Disallowed || !vm.TSOState.CanPlaceNewUserObject(vm)) { return(false); } vm.GlobalLink.RetrieveFromInventory(vm, ObjectPID, caller.PersistID, true, (uint guid, byte[] data) => { if (guid == 0) { return; //todo: error feedback? } GUID = guid; Data = data; Verified = true; vm.ForwardCommand(this); }); return(false); }
public override bool Execute(VM vm, VMAvatar caller) { var catalog = Content.Content.Get().WorldCatalog; var item = catalog.GetItemByGUID(GUID); if (Blacklist.Contains(GUID) || caller == null) { return(false); } //careful here! if the object can't be placed, we have to give the user their money back. if (TryPlace(vm, caller)) { return(true); } else if (vm.GlobalLink != null && item != null) { vm.GlobalLink.PerformTransaction(vm, false, uint.MaxValue, caller.PersistID, (int)item.Price, (bool success, int transferAmount, uint uid1, uint budget1, uint uid2, uint budget2) => { vm.SendCommand(new VMNetAsyncResponseCmd(0, new VMTransferFundsState { //update budgets on clients. id of 0 means there is no target thread. Responded = true, Success = success, TransferAmount = transferAmount, UID1 = uid1, Budget1 = budget1, UID2 = uid2, Budget2 = budget2 })); }); } return(false); }
public override bool Execute(VM vm, VMAvatar caller) { var catalog = Content.Content.Get().WorldCatalog; var item = catalog.GetItemByGUID(GUID); if (Blacklist.Contains(GUID) || caller == null) return false; //careful here! if the object can't be placed, we have to give the user their money back. if (TryPlace(vm, caller)) return true; else if (vm.GlobalLink != null && item != null) { vm.GlobalLink.PerformTransaction(vm, false, uint.MaxValue, caller.PersistID, (int)item.Price, (bool success, int transferAmount, uint uid1, uint budget1, uint uid2, uint budget2) => { vm.SendCommand(new VMNetAsyncResponseCmd(0, new VMTransferFundsState { //update budgets on clients. id of 0 means there is no target thread. Responded = true, Success = success, TransferAmount = transferAmount, UID1 = uid1, Budget1 = budget1, UID2 = uid2, Budget2 = budget2 })); }); } return false; }
public NetworkClient Client; //REPLACE WHEN MOVING OFF GONZONET!! public override bool Execute(VM vm) { Name = Name.Substring(0, Math.Min(Name.Length, 64)); var sim = vm.Context.CreateObjectInstance(VMAvatar.TEMPLATE_PERSON, LotTilePos.OUT_OF_WORLD, Direction.NORTH).Objects[0]; var mailbox = vm.Entities.FirstOrDefault(x => (x.Object.OBJ.GUID == 0xEF121974 || x.Object.OBJ.GUID == 0x1D95C9B0)); if (VM.UseWorld) { TSO.HIT.HITVM.Get().PlaySoundEvent("lot_enter"); } if (mailbox != null) { VMFindLocationFor.FindLocationFor(sim, mailbox, vm.Context); } sim.PersistID = ActorUID; VMAvatar avatar = (VMAvatar)sim; avatar.SkinTone = (Vitaboy.AppearanceType)SkinTone; avatar.SetPersonData(VMPersonDataVariable.Gender, (short)((Gender) ? 1 : 0)); avatar.BodyOutfit = BodyID; avatar.HeadOutfit = HeadID; avatar.Name = Name; ((VMTSOAvatarState)avatar.TSOState).Permissions = Permissions; return(true); }
private string GetAvatarString(VMAvatar ava) { int prefixNum = 3; if (ava.IsPet) { prefixNum = 5; } else if (ava.PersistID < 65536) { prefixNum = 4; } else { var permissionsLevel = ((VMTSOAvatarState)ava.TSOState).Permissions; switch (permissionsLevel) { case VMTSOAvatarPermissions.Visitor: prefixNum = 3; break; case VMTSOAvatarPermissions.Roommate: case VMTSOAvatarPermissions.BuildBuyRoommate: prefixNum = 2; break; case VMTSOAvatarPermissions.Admin: case VMTSOAvatarPermissions.Owner: prefixNum = 1; break; } } return(GameFacade.Strings.GetString("217", prefixNum.ToString()) + ava.ToString()); }
public override bool Execute(VM vm, VMAvatar caller) { VMEntity callee = vm.GetObjectById(CalleeID); if (caller == null && CallerID > 0) { //try get caller from normal id; caller = (vm.GetObjectById(CallerID) as VMAvatar); if (caller == null) { return(false); } } if (callee == null) { return(false); } if (callee is VMGameObject && ((VMGameObject)callee).Disabled > 0) { return(false); } if ((caller.Thread?.Queue?.Count ?? 0) >= VMThread.MAX_USER_ACTIONS) { return(false); } callee.PushUserInteraction(Interaction, caller, vm.Context, Global, new short[] { Param0, 0, 0, 0 }); return(true); }
public override bool Execute(VM vm, VMAvatar caller) { VMEntity obj = vm.GetObjectById(ObjectID); if (obj == null || caller == null || (obj is VMAvatar) || (((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Admin && obj.IsUserMovable(vm.Context, false) != VMPlacementError.Success)) { return(false); } if (((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Roommate) { return(false); } var result = obj.SetPosition(new LotTilePos(x, y, level), dir, vm.Context, VMPlaceRequestFlags.UserPlacement); if (result.Status == VMPlacementError.Success) { obj.MultitileGroup.ExecuteEntryPoint(11, vm.Context); //User Placement vm.SignalChatEvent(new VMChatEvent(caller.PersistID, VMChatEventType.Arch, caller.Name, vm.GetUserIP(caller.PersistID), "moved " + obj.ToString() + " to (" + x / 16f + ", " + y / 16f + ", " + level + ")" )); return(true); } else { return(false); } }
public override bool Verify(VM vm, VMAvatar caller) { if (Verified) { return(true); } //can only change permissions to and from build roommate. caller must be owner, and target must be roomie/build (cannot change owner or admin) if (caller == null || //caller must be on lot, have owner permissions ((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Owner) { return(false); } if (Level > VMTSOAvatarPermissions.BuildBuyRoommate || Level < VMTSOAvatarPermissions.Roommate) { return(false); //can only switch to build roomie or back. } if (!vm.TSOState.Roommates.Contains(TargetUID) || vm.TSOState.OwnerID == TargetUID) { return(false); } /* * var obj = vm.GetAvatarByPersist(TargetUID); * if (obj == null || ((VMTSOAvatarState)caller.TSOState).Permissions > VMTSOAvatarPermissions.BuildBuyRoommate || ((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Roommate || ((VMTSOAvatarState)caller.TSOState).Permissions == Level) return false; */ vm.GlobalLink.RequestRoommate(vm, TargetUID, 3, (byte)((Level == VMTSOAvatarPermissions.Roommate) ? 0 : 1)); return(false); }
public VMChatEvent(VMAvatar ava, VMChatEventType type, params string[] text) { SenderUID = ava?.PersistID ?? 0; Type = type; Text = text; Color = (ava?.TSOState as VMTSOAvatarState)?.ChatColor ?? Color.LightGray; }
public override PurchaseMode GetPurchaseMode(PurchaseMode desired, VMAvatar ava, uint guid, bool fromInventory) { if (desired > PurchaseMode.Donate) { return(PurchaseMode.Disallowed); } if (ava == null) { return(PurchaseMode.Disallowed); } if (ava.AvatarState.Permissions < VMTSOAvatarPermissions.Roommate) { return(PurchaseMode.Disallowed); } //todo: build/buy limits for inventory, but allow rare/non-catalog placement if (!vm.TS1 && !fromInventory) { var catalog = Content.Content.Get().WorldCatalog; var item = catalog.GetItemByGUID(guid); var whitelist = (ava.AvatarState.Permissions == VMTSOAvatarPermissions.Roommate) ? RoomieWhiteList : BuilderWhiteList; if (item == null || !whitelist.Contains(item.Value.Category)) { if (ava.AvatarState.Permissions != VMTSOAvatarPermissions.Admin) { return(PurchaseMode.Disallowed); } } } return(PurchaseMode.Normal); }
public void SetNameMessage(VMAvatar avatar) { Name = avatar.Name; Message = avatar.Message; Gender = avatar.GetPersonData(SimAntics.Model.VMPersonDataVariable.Gender) > 0; TTSContext?.Speak(Message.Replace('_', ' '), Gender, ((VMTSOAvatarState)avatar.TSOState).ChatTTSPitch); if (avatar.PersistID == 0) { BgColor = new Color(100, 100, 100); // NPC chat color } else if (((VMTSOAvatarState)avatar.TSOState).Permissions == VMTSOAvatarPermissions.Admin) { BgColor = new Color(180, 0, 0); // admin red color } else if (((VMTSOAvatarState)avatar.TSOState).Permissions == VMTSOAvatarPermissions.Visitor) { BgColor = new Color(30, 128, 30); // visitor green color } else { BgColor = new Color(8, 8, 128); // default blue color } Offscreen = false; if (Message == "") { Name = ""; } TextChanged(); }
public override DeleteMode GetDeleteMode(DeleteMode desired, VMAvatar ava, VMEntity obj) { if (desired > DeleteMode.Delete) { return(DeleteMode.Disallowed); } if (obj == null || ava == null) { return(DeleteMode.Disallowed); } if (desired == DeleteMode.Sendback) { if (obj.PersistID == 0 || obj is VMAvatar || !CanSendbackObject(ava, (VMGameObject)obj)) { desired = DeleteMode.Disallowed; } } else if (desired == DeleteMode.Delete) { if (obj is VMAvatar) { return((ava.AvatarState.Permissions < VMTSOAvatarPermissions.Admin) ? DeleteMode.Disallowed : DeleteMode.Delete); } if (ava.AvatarState.Permissions < VMTSOAvatarPermissions.Roommate) { desired = DeleteMode.Disallowed; } else if (obj.PersistID != 0 && ava.PersistID != (obj.TSOState as VMTSOObjectState).OwnerID && ava.AvatarState.Permissions != VMTSOAvatarPermissions.Admin) { desired = DeleteMode.Sendback; } } return(desired); }
public void Connect(uint UID, VMEntity invoker, VMEntity obj, VMAvatar avatar, bool joinable, VM vm) { if (InvokerToEOD.ContainsKey(invoker.ObjectID)) return; //uh, what? VMEODServer server = null; if (avatar != null && AvatarToEOD.ContainsKey(avatar.PersistID)) { //avatar already using an EOD... quickly abort this attempt with the stub EOD. joinable = false; UID = 0; avatar = null; } if (joinable) { if (!JoinableEODs.TryGetValue(obj.ObjectID, out server)) { server = new VMEODServer(UID, obj, joinable, vm); JoinableEODs[obj.ObjectID] = server; Servers.Add(server); } } else { server = new VMEODServer(UID, obj, joinable, vm); Servers.Add(server); } if (avatar != null) RegisterAvatar(avatar, server); RegisterInvoker(invoker, server); server.Connect(new VMEODClient(invoker, avatar, vm, UID)); }
public VMChatEvent(VMAvatar ava, VMChatEventType type, params string[] text) { SenderUID = ava?.PersistID ?? 0; Type = type; Text = text; Timestamp = DateTime.Now.ToShortTimeString(); Color = (ava?.TSOState as VMTSOAvatarState)?.ChatColor ?? Color.LightGray; }
public override bool Verify(VM vm, VMAvatar caller) { if (Verified == true) return true; //temporary... forward messages through tick broadcast //only run by server. Forward message to this avatar's connected EOD. if (caller == null) return false; vm.EODHost.Deliver(this, caller); return false; }
public void RegisterAvatar(VMAvatar avatar, VMEODServer server) { if (avatar == null) { return; } AvatarToEOD.Add(avatar.PersistID, server); }
private void SetHead(VMAvatar head, int i) { i = (int)DirectionUtils.PosMod(i, ActiveHeads.Count); head.HeadOutfit = new FSO.SimAntics.Model.VMOutfitReference(new Outfit() { TS1AppearanceID = ActiveHeads[i] + ".apr", TS1TextureID = ActiveHeadTex[i] }); }
public void UnregisterAvatar(VMAvatar avatar) { if (avatar == null) { return; } AvatarToEOD.Remove(avatar.PersistID); }
public VMAvatar CreateAvatar() { var avatar = new VMAvatar(TSO.Content.Content.Get().WorldObjects.Get(VMAvatar.TEMPLATE_PERSON)); this.InitWorldComponent(avatar.WorldUI); Blueprint.AddAvatar((AvatarComponent)avatar.WorldUI); VM.AddEntity(avatar); return avatar; }
public VMAvatar CreateAvatar() { var avatar = new VMAvatar(); this.InitWorldComponent(avatar.WorldUI); Blueprint.AddAvatar(avatar.WorldUI); VM.AddEntity(avatar); return avatar; }
public override bool Verify(VM vm, VMAvatar caller) { if (caller == null && FromNet) { return(false); } return(true); }
public override bool Execute(VM vm, VMAvatar caller) { //only run by client. send to their UI handler. //TODO: DO NOT BROADCAST VIA SYNC COMMAND INTERFACE TO ALL. ONLY TO TARGET! if (caller != null && caller.PersistID == vm.MyUID) { vm.SignalEODMessage(this); } return true; }
public void LeaveLot(VM vm, VMAvatar avatar) { //TODO: in the global server, this will save the avatar (and possibly lot) states and send back to server. if (avatar.PersistID == vm.MyUID) { //stub has some functionality here. if we have left lot, disconnect. vm.CloseNet(VMCloseNetReason.LeaveLot); } avatar.Delete(true, vm.Context); vm.Context.VM.SignalChatEvent(new VMChatEvent(avatar.PersistID, VMChatEventType.Leave, avatar.Name)); }
public override bool Execute(VM vm, VMAvatar sim) { if (sim != null && !sim.Dead) { // the user has left the lot with their sim still on it... // force leave lot. generate an action with incredibly high priority and cancel current // TODO: timeout for forceful removal sim.UserLeaveLot(); } return true; }
public void Deliver(VMNetEODMessageCmd msg, VMAvatar avatar) { VMEODServer server = null; if (AvatarToEOD.TryGetValue(avatar.PersistID, out server)) { var avatarClient = server.Clients.FirstOrDefault(x => x.Avatar == avatar); if (avatarClient != null) { server.Deliver(msg, avatarClient); } } }
public void ForceDisconnect(VMAvatar avatar) { VMEODServer server = null; if (AvatarToEOD.TryGetValue(avatar.PersistID, out server)) { var avatarClient = server.Clients.FirstOrDefault(x => x.Avatar == avatar); if (avatarClient != null) { server.Disconnect(avatarClient); } } }
public void Tick(VMAvatar avatar, VMContext context) { if (context.Clock.Minutes == LastMinute) return; LastMinute = context.Clock.Minutes; string category = "Skills"; string sleepState = (avatar.GetMotiveData(VMMotive.SleepState) == 0)?"Awake":"Asleep"; int moodSum = 0; for (int i = 0; i < 7; i++) { if (avatar.IsPet && i == 5) return; float lotMul = LotMotives.GetNum(category + "_" + LotMotiveNames[i] + "Weight"); float frac = 0; var motive = avatar.GetMotiveData(DecrementMotives[i]); var r_Hunger = (SimMotives.GetNum("HungerDecrementRatio") * (100+avatar.GetMotiveData(VMMotive.Hunger))) * LotMotives.GetNum(category+"_HungerWeight"); switch (i) { case 0: frac = r_Hunger; break; case 1: frac = (SimMotives.GetNum("ComfortDecrementActive") * lotMul); break; case 2: frac = (SimMotives.GetNum("HygieneDecrement" + sleepState) * lotMul); break; case 3: frac = (SimMotives.GetNum("BladderDecrement" + sleepState) * lotMul) + (SimMotives.GetNum("HungerToBladderMultiplier") * r_Hunger); break; case 4: frac = (SimMotives.GetNum("EnergySpan") / (60 * SimMotives.GetNum("WakeHours"))); // TODO: wrong but appears to be close? need one which uses energy weight, which is about 2.4 on skills break; case 5: frac = (sleepState == "Asleep") ? 0 : (SimMotives.GetNum("EntDecrementAwake") * lotMul); break; case 6: frac = (SimMotives.GetNum("SocialDecrementBase") + (SimMotives.GetNum("SocialDecrementMultiplier") * (100+motive))) * lotMul; frac /= 2; //make this less harsh right now, til I can work out how multiplayer bonus is meant to work break; } MotiveFractions[i] += (short)(frac * 1000); if (MotiveFractions[i] >= 1000) { motive -= (short)(MotiveFractions[i] / 1000); MotiveFractions[i] %= 1000; if (motive < -100) motive = -100; avatar.SetMotiveData(DecrementMotives[i], motive); } moodSum += motive; } avatar.SetMotiveData(VMMotive.Mood, (short)(moodSum / 7)); }
public void Tick(VMAvatar avatar) { if (PerHourChange != 0) { double rate = (PerHourChange/60.0)/30.0; //remember to fix when we implement the clock! right now assumes time for an hour is a realtime minute fractional += rate; if (Math.Abs(fractional) >= 1) { var motive = avatar.GetMotiveData(Motive); motive += (short)(fractional); fractional %= 1.0; if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { motive = MaxValue; Clear(); } avatar.SetMotiveData(Motive, motive); } } }
public void Tick(VMAvatar avatar) { Ticked = true; if (PerHourChange != 0) { double rate = (PerHourChange/60.0)/(30.0*5.0); //timed for 5 second minutes fractional += rate; if (Math.Abs(fractional) >= 1) { var motive = avatar.GetMotiveData(Motive); if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { return; } //we're already over, do nothing. (do NOT clamp) motive += (short)(fractional); fractional %= 1.0; if (((rate > 0) && (motive > MaxValue)) || ((rate < 0) && (motive < MaxValue))) { motive = MaxValue; } //DO NOT CLEAR MOTIVE WHEN IT HITS MAX VALUE! fixes pet, maybe shower. avatar.SetMotiveData(Motive, motive); } } }
public override bool Execute(VM vm, VMAvatar caller) { VMEntity obj = vm.GetObjectById(ObjectID); if (obj == null || caller == null || (obj is VMAvatar)) return false; if (((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Roommate) return false; var result = obj.SetPosition(new LotTilePos(x, y, level), dir, vm.Context); if (result.Status == VMPlacementError.Success) { obj.MultitileGroup.ExecuteEntryPoint(11, vm.Context); //User Placement vm.SignalChatEvent(new VMChatEvent(caller.PersistID, VMChatEventType.Arch, caller.Name, vm.GetUserIP(caller.PersistID), "moved " + obj.ToString() +" to (" + x / 16f + ", " + y / 16f + ", " + level + ")" )); return true; } else { return false; } }
public override bool Execute(VM vm, VMAvatar caller) { if (((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Roommate) return false; VMEntity obj = vm.GetObjectById(ObjectID); if (obj == null || caller == null || (obj is VMAvatar)) return false; obj.Delete(CleanupAll, vm.Context); //TODO: Check if user is owner of object. Maybe sendback to owner inventory if a roommate deletes. // If we're the server, tell the global server to give their money back. if (vm.GlobalLink != null) { vm.GlobalLink.PerformTransaction(vm, false, uint.MaxValue, caller.PersistID, obj.MultitileGroup.Price, (bool success, int transferAmount, uint uid1, uint budget1, uint uid2, uint budget2) => { vm.SendCommand(new VMNetAsyncResponseCmd(0, new VMTransferFundsState { //update budgets on clients. id of 0 means there is no target thread. Responded = true, Success = success, TransferAmount = transferAmount, UID1 = uid1, Budget1 = budget1, UID2 = uid2, Budget2 = budget2 })); }); } vm.SignalChatEvent(new VMChatEvent(caller.PersistID, VMChatEventType.Arch, caller.Name, vm.GetUserIP(caller.PersistID), "deleted " + obj.ToString() )); return true; }
public VMEODClient(VMEntity invoker, VMAvatar avatar, VM vm, uint PID) { Invoker = invoker; Avatar = avatar; this.vm = vm; ActivePID = PID; }
public override bool Verify(VM vm, VMAvatar caller) { if (Verified) return true; //set internally when transaction succeeds. trust that the verification happened. if (caller == null || //caller must be on lot, have build permissions ((VMTSOAvatarState)caller.TSOState).Permissions < VMTSOAvatarPermissions.Roommate) return false; //get entry in catalog. first verify if it can be bought at all. (if not, error out) //TODO: error feedback for client var catalog = Content.Content.Get().WorldCatalog; var item = catalog.GetItemByGUID(GUID); if (item == null || item.Category == -1) { if (((VMTSOAvatarState)caller.TSOState).Permissions == VMTSOAvatarPermissions.Admin) return true; return false; //not purchasable } //TODO: fine grained purchase control based on user status //perform the transaction. If it succeeds, requeue the command vm.GlobalLink.PerformTransaction(vm, false, caller.PersistID, uint.MaxValue, (int)item.Price, (bool success, int transferAmount, uint uid1, uint budget1, uint uid2, uint budget2) => { if (success) { Verified = true; vm.ForwardCommand(this); } vm.SendCommand(new VMNetAsyncResponseCmd(0, new VMTransferFundsState { //update budgets on clients. id of 0 means there is no target thread. Responded = true, Success = success, TransferAmount = transferAmount, UID1 = uid1, Budget1 = budget1, UID2 = uid2, Budget2 = budget2 })); }); return false; }
private bool TryPlace(VM vm, VMAvatar caller) { var catalog = Content.Content.Get().WorldCatalog; var item = catalog.GetItemByGUID(GUID); var group = vm.Context.CreateObjectInstance(GUID, new LotTilePos(x, y, level), dir); if (group == null) return false; group.ExecuteEntryPoint(11, vm.Context); //User Placement if (group.Objects.Count == 0) return false; if (group.BaseObject.Position == LotTilePos.OUT_OF_WORLD) { group.Delete(vm.Context); return false; } int salePrice = 0; if (item != null) salePrice = (int)item.Price; var def = group.BaseObject.MasterDefinition; if (def == null) def = group.BaseObject.Object.OBJ; var limit = def.DepreciationLimit; if (salePrice > limit) //only try to deprecate if we're above the limit. Prevents objects with a limit above their price being money fountains. { salePrice -= def.InitialDepreciation; if (salePrice < limit) salePrice = limit; } group.Price = (int)salePrice; foreach (var obj in group.Objects) { if (obj is VMGameObject) ((VMTSOObjectState)obj.TSOState).OwnerID = caller.PersistID; } vm.SignalChatEvent(new VMChatEvent(caller.PersistID, VMChatEventType.Arch, caller.Name, vm.GetUserIP(caller.PersistID), "placed " + group.BaseObject.ToString() + " at (" + x / 16f + ", " + y / 16f + ", " + level + ")" )); return true; }
private VMAnimationState PlayAnim(string name, VMAvatar avatar) { var animation = FSO.Content.Content.Get().AvatarAnimations.Get(name + ".anim"); var state = new VMAnimationState(animation, false); avatar.Animations.Add(state); return state; }
public void RequestRoommate(VM vm, VMAvatar avatar) { //in final game: signal to city server persistant roommate request state. //right now: immedaiately add as roommate vm.ForwardCommand(new VMChangePermissionsCmd() { TargetUID = avatar.PersistID, Level = VMTSOAvatarPermissions.Roommate, Verified = true }); }
public override bool Verify(VM vm, VMAvatar caller) { Name = Name.Replace("\r\n", ""); if (Verified == true) return true; if (Ticket == null) Ticket = "local" + ":" + Name; var tempName = Name; //obviously not a concern for final server. but for now... prevents people logging in with 2x same persist int i = 1; while (vm.Entities.Any(x => (x is VMAvatar) && ((VMAvatar)x).Name == tempName)) { tempName = Name + " (" + (i++) + ")"; } Name = tempName; if (FromNet && RequesterID == uint.MaxValue - 1) return false; //only server can set themselves as server... RequesterID = ActorUID; vm.GlobalLink.ObtainAvatarFromTicket(vm, Ticket, (uint persistID, VMTSOAvatarPermissions permissions) => { //first, verify if their sim has left the lot yet. if not, they cannot join until they have left. //(only really happens with an immediate rejoin) if (vm.Entities.FirstOrDefault(x => x.PersistID == persistID) != null && Client != null) { Client.Disconnect(); //would like to send a message but need a rework of VMServerDriver to make it happen return; } //TODO: a lot more persist state this.ActorUID = persistID; this.Permissions = permissions; this.Verified = true; vm.ForwardCommand(this); }); return false; }
private Animation PlayAnim(string name, VMAvatar avatar) { var animation = TSO.Content.Content.Get().AvatarAnimations.Get(name + ".anim"); avatar.CurrentAnimation = animation; avatar.CurrentAnimationState = new VMAnimationState(); avatar.Avatar.LeftHandGesture = SimHandGesture.Idle; avatar.Avatar.RightHandGesture = SimHandGesture.Idle; foreach (var motion in animation.Motions) { if (motion.TimeProperties == null) { continue; } foreach (var tp in motion.TimeProperties) { foreach (var item in tp.Items) { avatar.CurrentAnimationState.TimePropertyLists.Add(item); } } } /** Sort time property lists by time **/ avatar.CurrentAnimationState.TimePropertyLists.Sort(new TimePropertyListItemSorter()); return animation; }
public override bool Verify(VM vm, VMAvatar caller) { return !FromNet; }
public override bool Execute(VM vm, VMAvatar avatar) { if (Message.Length == 0) return false; if (Message.Length > 200) Message = Message.Substring(0, 200); if (avatar == null) return false; if (Message[0] == '/' && Message.Length > 1) { var spaceIndex = Message.IndexOf(' '); if (spaceIndex == -1) spaceIndex = Message.Length; if ((FromNet && ((VMTSOAvatarState)avatar.TSOState).Permissions < VMTSOAvatarPermissions.Admin) || !(vm.Driver is VMServerDriver)) return false; //commands are only run from the server sim right now var cmd = Message.Substring(1, spaceIndex - 1); var args = Message.Substring(Math.Min(Message.Length, spaceIndex + 1), Math.Max(0, Message.Length - (spaceIndex + 1))); var server = (VMServerDriver)vm.Driver; VMEntity sim; switch (cmd.ToLowerInvariant()) { case "ban": server.BanUser(vm, args); break; case "banip": server.BanIP(args); vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "Added " + args + " to the IP ban list.")); break; case "unban": server.SandboxBans.Remove(args.ToLowerInvariant().Trim(' ')); vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "Removed " + args + " from the IP ban list.")); break; case "banlist": string result = ""; foreach (var ban in server.SandboxBans.List()) result += ban + "\r\n"; vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "==== BANNED IPS: ==== \r\n"+result)); break; case "builder": sim = vm.Entities.Where(x => x is VMAvatar && x.ToString().ToLowerInvariant().Trim(' ') == args.ToLowerInvariant().Trim(' ')).FirstOrDefault(); if (sim != null) { vm.ForwardCommand(new VMChangePermissionsCmd() { TargetUID = sim.PersistID, Level = VMTSOAvatarPermissions.BuildBuyRoommate, Verified = true }); vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "Made " + sim.Name + " a build-roommate.")); } break; case "admin": sim = vm.Entities.Where(x => x is VMAvatar && x.ToString().ToLowerInvariant().Trim(' ') == args.ToLowerInvariant().Trim(' ')).FirstOrDefault(); if (sim != null) { vm.ForwardCommand(new VMChangePermissionsCmd() { TargetUID = sim.PersistID, Level = VMTSOAvatarPermissions.Admin, Verified = true }); vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "Made " + sim.Name + " an admin.")); } break; case "roomie": sim = vm.Entities.Where(x => x is VMAvatar && x.ToString().ToLowerInvariant().Trim(' ') == args.ToLowerInvariant().Trim(' ')).FirstOrDefault(); if (sim != null) { vm.ForwardCommand(new VMChangePermissionsCmd() { TargetUID = sim.PersistID, Level = VMTSOAvatarPermissions.Roommate, Verified = true }); vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "Made " + sim.Name + " a roommate.")); } break; case "visitor": sim = vm.Entities.Where(x => x is VMAvatar && x.ToString().ToLowerInvariant().Trim(' ') == args.ToLowerInvariant().Trim(' ')).FirstOrDefault(); if (sim != null) { vm.ForwardCommand(new VMChangePermissionsCmd() { TargetUID = sim.PersistID, Level = VMTSOAvatarPermissions.Visitor, Verified = true }); vm.SignalChatEvent(new VMChatEvent(0, VMChatEventType.Generic, "Made " + sim.Name + " a visitor.")); } break; case "close": if (FromNet) return false; vm.CloseNet(VMCloseNetReason.ServerShutdown); break; } return true; } else { vm.SignalChatEvent(new VMChatEvent(avatar.PersistID, VMChatEventType.Message, avatar.Name, Message)); avatar.Message = Message; return true; } }
public void RegisterAvatar(VMAvatar avatar, VMEODServer server) { if (avatar == null) return; AvatarToEOD.Add(avatar.PersistID, server); }
public void UnregisterAvatar(VMAvatar avatar) { if (avatar == null) return; AvatarToEOD.Remove(avatar.PersistID); }
public virtual bool Execute(VM vm, VMAvatar caller) { return Execute(vm); }
public override bool Verify(VM vm, VMAvatar caller) { return Verified; }
private bool CanShooAvatar(VMAvatar avatar) { VMRoutingFrame topRoute = null; //look for top frame for (int i = avatar.Thread.Stack.Count - 1; i >= 0; i--) { var frame = avatar.Thread.Stack[i]; if (frame is VMRoutingFrame) { topRoute = (VMRoutingFrame)frame; } } //check both the top route frame its parent for ones postponed by shooing, //as the top frame will most likely be walking as part of the shoo, and the postponed frame will be the parent. //check the parent too just in case they got shooed this frame by another avatar if (topRoute != null && (topRoute.State == VMRoutingFrameState.SHOOED || (topRoute.ParentRoute != null && topRoute.ParentRoute.State == VMRoutingFrameState.SHOOED))) return false; //check if the shoo interaction is present on their action queue. callee GUID (destination obj) and //interaction id must match. if (avatar.Thread.Queue.Any(x => x.Callee.Object.GUID == GOTO_GUID && x.InteractionNumber == SHOO_INTERACTION)) return false; return true; }
//verifies commands sent by clients before running and forwarding them. //if "Verify" returns true, the server runs the command and it is sent to clients //this prevents forwarding bogus requests - though some verifications are performed as the command is sequenced. //certain commands like "StateSyncCommand" cannot be forwarded from clients. //note - that returning false from here will only prevent the command from being forwarded IMMEDIATELY. //Architecture and Buy Object commands perform asynchronous transactions and then resend their command on success later. //verify is not run on clients. public virtual bool Verify(VM vm, VMAvatar caller) { return true; }