public void MoveSelected(Vector2 pos, sbyte level) { Holding.TilePos = pos; Holding.Level = level; //first, eject the object from any slots for (int i = 0; i < Holding.Group.Objects.Count; i++) { var obj = Holding.Group.Objects[i]; if (obj.Container != null) { obj.Container.ClearSlot(obj.ContainerSlot); } } //rotate through to try all configurations var dir = Holding.Dir; VMPlacementError status = VMPlacementError.Success; if (!Holding.IsBought) { if (DonateMode && !vm.TSOState.CanPlaceNewDonatedObject(vm)) { status = VMPlacementError.TooManyObjectsOnTheLot; } else if (!DonateMode && !vm.TSOState.CanPlaceNewUserObject(vm)) { status = VMPlacementError.TooManyObjectsOnTheLot; } } if (status == VMPlacementError.Success) { for (int i = 0; i < 4; i++) { status = Holding.Group.ChangePosition(LotTilePos.FromBigTile((short)pos.X, (short)pos.Y, level), dir, vm.Context, VMPlaceRequestFlags.UserPlacement).Status; if (status != VMPlacementError.MustBeAgainstWall) { break; } dir = (Direction)((((int)dir << 6) & 255) | ((int)dir >> 2)); } if (Holding.Dir != dir) { Holding.Dir = dir; } } if (status != VMPlacementError.Success) { Holding.Group.ChangePosition(LotTilePos.OUT_OF_WORLD, Holding.Dir, vm.Context, VMPlaceRequestFlags.UserPlacement); Holding.Group.SetVisualPosition(new Vector3(pos, (((Holding.Group.Objects[0].GetValue(VMStackObjectVariable.AllowedHeightFlags) & 1) == 1) ? 0 : 4f / 5f) + (level - 1) * 2.95f), //^ if we can't be placed on the floor, default to table height. Holding.Dir, vm.Context); } for (int i = 0; i < Holding.Group.Objects.Count; i++) { var target = Holding.Group.Objects[i]; var tpos = target.VisualPosition; tpos.Z = (level - 1) * 2.95f; Holding.CursorTiles[i].MultitileGroup.SetVisualPosition(tpos, Holding.Dir, vm.Context); } Holding.CanPlace = status; }
private void OnMouse(UIMouseEventType type, UpdateState state) { if (!vm.Ready) { return; } if (type == UIMouseEventType.MouseOver) { if (QueryPanel.Mode == 1) { QueryPanel.Active = false; } MouseIsOn = true; } else if (type == UIMouseEventType.MouseOut) { MouseIsOn = false; Tooltip = null; } else if (type == UIMouseEventType.MouseDown) { if (!LiveMode) { if (CustomControl != null) { CustomControl.MouseDown(state); } else { ObjectHolder.MouseDown(state); } return; } if (PieMenu == null && ActiveEntity != null) { VMEntity obj; //get new pie menu, make new pie menu panel for it var tilePos = World.State.WorldSpace.GetTileAtPosWithScroll(new Vector2(state.MouseState.X, state.MouseState.Y) / FSOEnvironment.DPIScaleFactor); LotTilePos targetPos = LotTilePos.FromBigTile((short)tilePos.X, (short)tilePos.Y, World.State.Level); if (vm.Context.SolidToAvatars(targetPos).Solid) { targetPos = LotTilePos.OUT_OF_WORLD; } GotoObject.SetPosition(targetPos, Direction.NORTH, vm.Context); bool objSelected = ObjectHover > 0 && InteractionsAvailable; if (objSelected || (GotoObject.Position != LotTilePos.OUT_OF_WORLD && ObjectHover <= 0)) { HITVM.Get().PlaySoundEvent(UISounds.PieMenuAppear); if (objSelected) { obj = vm.GetObjectById(ObjectHover); } else { obj = GotoObject; } obj = obj.MultitileGroup.GetInteractionGroupLeader(obj); var menu = obj.GetPieMenu(vm, ActiveEntity, false); if (menu.Count != 0) { PieMenu = new UIPieMenu(menu, obj, ActiveEntity, this); this.Add(PieMenu); PieMenu.X = state.MouseState.X / FSOEnvironment.DPIScaleFactor; PieMenu.Y = state.MouseState.Y / FSOEnvironment.DPIScaleFactor; PieMenu.UpdateHeadPosition(state.MouseState.X, state.MouseState.Y); } } else { HITVM.Get().PlaySoundEvent(UISounds.Error); state.UIState.TooltipProperties.Show = true; state.UIState.TooltipProperties.Color = Color.Black; state.UIState.TooltipProperties.Opacity = 1; state.UIState.TooltipProperties.Position = new Vector2(state.MouseState.X, state.MouseState.Y); state.UIState.Tooltip = GameFacade.Strings.GetString("159", "0"); state.UIState.TooltipProperties.UpdateDead = false; ShowTooltip = true; TipIsError = true; } } else { if (PieMenu != null) { PieMenu.RemoveSimScene(); } this.Remove(PieMenu); PieMenu = null; } } else if (type == UIMouseEventType.MouseUp) { if (!LiveMode) { if (CustomControl != null) { CustomControl.MouseUp(state); } else { ObjectHolder.MouseUp(state); } return; } state.UIState.TooltipProperties.Show = false; state.UIState.TooltipProperties.Opacity = 0; ShowTooltip = false; TipIsError = false; } }
public override void Update(UpdateState state) { base.Update(state); Cheats.Update(state); if (!vm.Ready) { return; } if (ActiveEntity == null || ActiveEntity.Dead || ActiveEntity.PersistID != SelectedSimID) { ActiveEntity = vm.Entities.FirstOrDefault(x => x is VMAvatar && x.PersistID == SelectedSimID); //try and hook onto a sim if we have none selected. if (ActiveEntity == null) { ActiveEntity = vm.Entities.FirstOrDefault(x => x is VMAvatar); } if (!FoundMe && ActiveEntity != null) { vm.Context.World.State.CenterTile = new Vector2(ActiveEntity.VisualPosition.X, ActiveEntity.VisualPosition.Y); vm.Context.World.State.ScrollAnchor = null; FoundMe = true; } Queue.QueueOwner = ActiveEntity; } if (GotoObject == null) { GotoObject = vm.Context.CreateObjectInstance(GOTO_GUID, LotTilePos.OUT_OF_WORLD, Direction.NORTH, true).Objects[0]; } if (ActiveEntity != null && BlockingDialog != null) { //are we still waiting on a blocking dialog? if not, cancel. if (ActiveEntity.Thread != null && (ActiveEntity.Thread.BlockingState == null || !(ActiveEntity.Thread.BlockingState is VMDialogResult))) { UIScreen.RemoveDialog(BlockingDialog); LastDialogID = 0; BlockingDialog = null; } } if (Visible) { if (ShowTooltip) { state.UIState.TooltipProperties.UpdateDead = false; } bool scrolled = false; if (RMBScroll) { World.State.ScrollAnchor = null; Vector2 scrollBy = new Vector2(); if (state.TouchMode) { scrollBy = new Vector2(RMBScrollX - state.MouseState.X, RMBScrollY - state.MouseState.Y); RMBScrollX = state.MouseState.X; RMBScrollY = state.MouseState.Y; scrollBy /= 128f; scrollBy /= FSOEnvironment.DPIScaleFactor; } else { scrollBy = new Vector2(state.MouseState.X - RMBScrollX, state.MouseState.Y - RMBScrollY); scrollBy *= 0.0005f; } World.Scroll(scrollBy); scrolled = true; } if (MouseIsOn) { if (state.MouseState.RightButton == ButtonState.Pressed) { if (RMBScroll == false) { RMBScroll = true; RMBScrollX = state.MouseState.X; RMBScrollY = state.MouseState.Y; } } else { RMBScroll = false; if (!scrolled && GlobalSettings.Default.EdgeScroll && !state.TouchMode) { scrolled = World.TestScroll(state); } } } if (LiveMode) { LiveModeUpdate(state, scrolled); } else if (CustomControl != null) { CustomControl.Update(state, scrolled); } else { ObjectHolder.Update(state, scrolled); } //set cutaway around mouse if (vm.Context.Blueprint != null) { World.State.DynamicCutaway = (WallsMode == 1); //first we need to cycle the rooms that are being cutaway. Keep this up even if we're in all-cut mode. var mouseTilePos = World.State.WorldSpace.GetTileAtPosWithScroll(new Vector2(state.MouseState.X, state.MouseState.Y) / FSOEnvironment.DPIScaleFactor); var roomHover = vm.Context.GetRoomAt(LotTilePos.FromBigTile((short)(mouseTilePos.X), (short)(mouseTilePos.Y), World.State.Level)); var outside = (vm.Context.RoomInfo[roomHover].Room.IsOutside); if (!outside && !CutRooms.Contains(roomHover)) { CutRooms.Add(roomHover); //outside hover should not persist like with other rooms. } while (CutRooms.Count > 3) { CutRooms.Remove(CutRooms.ElementAt(0)); } if (LastWallMode != WallsMode) { if (WallsMode == 0) //walls down { LastCuts = new bool[vm.Context.Architecture.Width * vm.Context.Architecture.Height]; vm.Context.Blueprint.Cutaway = LastCuts; vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED)); for (int i = 0; i < LastCuts.Length; i++) { LastCuts[i] = true; } } else if (WallsMode == 1) { MouseCutRect = new Rectangle(); LastCutRooms = new HashSet <uint>() { uint.MaxValue }; //must regenerate cuts } else //walls up or roof { LastCuts = new bool[vm.Context.Architecture.Width * vm.Context.Architecture.Height]; vm.Context.Blueprint.Cutaway = LastCuts; vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED)); } LastWallMode = WallsMode; } if (WallsMode == 1) { int recut = 0; var finalRooms = new HashSet <uint>(CutRooms); var newCut = new Rectangle((int)(mouseTilePos.X - 2.5), (int)(mouseTilePos.Y - 2.5), 5, 5); newCut.X -= VMArchitectureTools.CutCheckDir[(int)World.State.Rotation][0] * 2; newCut.Y -= VMArchitectureTools.CutCheckDir[(int)World.State.Rotation][1] * 2; if (newCut != MouseCutRect) { MouseCutRect = newCut; recut = 1; } if (LastFloor != World.State.Level || LastRotation != World.State.Rotation || !finalRooms.SetEquals(LastCutRooms)) { LastCuts = VMArchitectureTools.GenerateRoomCut(vm.Context.Architecture, World.State.Level, World.State.Rotation, finalRooms); recut = 2; LastFloor = World.State.Level; LastRotation = World.State.Rotation; } LastCutRooms = finalRooms; if (recut > 0) { var finalCut = new bool[LastCuts.Length]; Array.Copy(LastCuts, finalCut, LastCuts.Length); var notableChange = VMArchitectureTools.ApplyCutRectangle(vm.Context.Architecture, World.State.Level, finalCut, MouseCutRect); if (recut > 1 || notableChange || LastRectCutNotable) { vm.Context.Blueprint.Cutaway = finalCut; vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED)); } LastRectCutNotable = notableChange; } } } } }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMSetToNextOperand)args; var targetValue = VMMemory.GetVariable(context, operand.TargetOwner, operand.TargetData); var entities = context.VM.Entities; VMEntity Pointer = context.VM.GetObjectById(targetValue); //re-evaluation of what this actually does: //tries to find the next object id (from the previous) that meets a specific condition. //the previous object id is supplied via the target variable // //we should take the first result with object id > targetValue. if (operand.SearchType == VMSetToNextSearchType.PartOfAMultipartTile) { var target = context.VM.GetObjectById(targetValue); if (target == null || (!target.MultitileGroup.MultiTile)) { return(VMPrimitiveExitCode.GOTO_FALSE); //single part } else { var group = target.MultitileGroup.Objects; bool found = false; short bestID = 0; short smallestID = 0; for (int i = 0; i < group.Count; i++) { var temp = group[i]; if (temp.ObjectID < smallestID || smallestID == 0) { smallestID = temp.ObjectID; } if (temp.ObjectID > targetValue) { if ((!found) || (temp.ObjectID < bestID)) { found = true; bestID = temp.ObjectID; } } } if (found) { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, bestID); return(VMPrimitiveExitCode.GOTO_TRUE); } else { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, smallestID); return(VMPrimitiveExitCode.GOTO_TRUE); } } } else if (operand.SearchType == VMSetToNextSearchType.ObjectAdjacentToObjectInLocal) { VMEntity anchor = context.VM.GetObjectById((short)context.Locals[operand.Local]); int ptrDir = -1; targetValue = 0; if (Pointer != null) { ptrDir = getAdjDir(anchor, Pointer); if (ptrDir == 3) { return(VMPrimitiveExitCode.GOTO_FALSE); //reached end } } //iterate through all following dirs til we find an object for (int i = ptrDir + 1; i < 4; i++) { var off = AdjStep[i]; var adj = context.VM.Context.SetToNextCache.GetObjectsAt(LotTilePos.FromBigTile( (short)(anchor.Position.TileX + off.X), (short)(anchor.Position.TileY + off.Y), anchor.Position.Level)); if (adj != null && adj.Count > 0) { //lists are ordered by object id. first is the smallest. VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, adj[0].ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } return(VMPrimitiveExitCode.GOTO_FALSE); } else { //if we've cached the search type, use that instead of all objects switch (operand.SearchType) { case VMSetToNextSearchType.ObjectOnSameTile: entities = context.VM.Context.SetToNextCache.GetObjectsAt(Pointer.Position); break; case VMSetToNextSearchType.Person: entities = context.VM.Context.SetToNextCache.Avatars; break; case VMSetToNextSearchType.ObjectOfType: entities = context.VM.Context.SetToNextCache.GetObjectsByGUID(operand.GUID); break; } if (entities == null) { return(VMPrimitiveExitCode.GOTO_FALSE); } bool loop = (operand.SearchType == VMSetToNextSearchType.ObjectOnSameTile); VMEntity first = null; for (int i = 0; i < entities.Count; i++) //generic search through all objects { var temp = entities[i]; bool found = false; if (temp.ObjectID > targetValue || loop) { switch (operand.SearchType) { //manual search types case VMSetToNextSearchType.NonPerson: found = (temp.GetType() == typeof(VMGameObject)); break; case VMSetToNextSearchType.NeighborId: throw new VMSimanticsException("Not implemented!", context); case VMSetToNextSearchType.ObjectWithCategoryEqualToSP0: found = (temp.Object.OBJ.FunctionFlags == context.Args[0]); //I'm assuming that means "Stack parameter 0", that category means function and that it needs to be exactly the same (no subsets) break; case VMSetToNextSearchType.NeighborOfType: throw new VMSimanticsException("Not implemented!", context); case VMSetToNextSearchType.Career: throw new VMSimanticsException("Not implemented!", context); case VMSetToNextSearchType.ClosestHouse: throw new VMSimanticsException("Not implemented!", context); default: //set to next object, or cached search. found = true; break; } if (temp.ObjectID <= targetValue && found) { //remember the first element in case we need to loop back to it (set to next tile on same location) if (first == null) { first = temp; } found = false; } } if (found) { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, temp.ObjectID); return(VMPrimitiveExitCode.GOTO_TRUE); } } if (loop) { if (first == null) { return(VMPrimitiveExitCode.GOTO_FALSE); //no elements of this kind at all. } else { VMMemory.SetVariable(context, operand.TargetOwner, operand.TargetData, first.ObjectID); //set to loop, so go back to lowest obj id. return(VMPrimitiveExitCode.GOTO_TRUE); } //loop around } } return(VMPrimitiveExitCode.GOTO_FALSE); //ran out of objects to test }
public static uint FIRE_GUID = 0x24C95F99; //probably different for ts1 public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMBurnOperand)args; if (!context.VM.TS1 && context.VM.Tuning.GetTuning("special", 0, 0) != 1f) { return(VMPrimitiveExitCode.GOTO_FALSE); //fire disabled for now } if ((int)context.VM.Context.NextRandom(10000) >= context.VM.Context.Clock.FirePercent) { return(VMPrimitiveExitCode.GOTO_FALSE); } //as fires burn, the chance they can spread lowers dramatically. context.VM.Context.Clock.FirePercent -= 500; // lower by 5% every spread. 40 spreads reaches 0. if (context.VM.Context.Clock.FirePercent < 0) { context.VM.Context.Clock.FirePercent = 0; } //begin the burn setup. var arch = context.VM.Context.Architecture; var query = context.VM.Context.ObjectQueries; bool[] fires = new bool[arch.Width * arch.Height]; var spread = new Queue <LotTilePos>(); LotTilePos pos; switch (operand.Type) { case VMBurnType.FrontOfStackObject: pos = new LotTilePos(context.StackObject.Position); switch (context.StackObject.Direction) { case Direction.SOUTH: pos.y += 16; break; case Direction.WEST: pos.x -= 16; break; case Direction.EAST: pos.x += 16; break; case Direction.NORTH: pos.y -= 16; break; } break; case VMBurnType.StackObject: default: pos = context.StackObject.Position; break; } bool first = true; bool madeAFire = false; spread.Enqueue(pos); while (spread.Count > 0) { var item = spread.Dequeue(); var objat = query.GetObjectsAt(item) ?? new List <VMEntity>(); if (first && !(objat?.Any(x => x.Object.OBJ.GUID == FIRE_GUID) ?? false)) { madeAFire = true; context.VM.Context.CreateObjectInstance(FIRE_GUID, LotTilePos.FromBigTile(pos.TileX, pos.TileY, pos.Level), Direction.NORTH); } first = false; foreach (var obj in objat) { var inUse = obj.IsInUse(context.VM.Context, true) || (obj is VMAvatar && ((VMAvatar)obj).GetPersonData(Model.VMPersonDataVariable.IsGhost) > 0); if (inUse) { continue; } foreach (var sobj in obj.MultitileGroup.Objects) { //attempt to add fire for this element. //for each tile add a spread. //is this object burnable? if so, set it as burning if (sobj.Position.Level != pos.Level) { continue; } if ((((VMEntityFlags2)sobj.GetValue(Model.VMStackObjectVariable.FlagField2) & VMEntityFlags2.Burns) > 0) && !sobj.GetFlag(VMEntityFlags.FireProof)) { sobj.SetFlag(VMEntityFlags.Burning, true); var fpos = sobj.Position; var index = fpos.TileX + fpos.TileY * arch.Width; if (fires[index] || (query.GetObjectsAt(fpos)?.Any(x => x.Object.OBJ.GUID == FIRE_GUID) ?? false)) { fires[index] = true; continue; } spread.Enqueue(fpos); madeAFire = true; context.VM.Context.CreateObjectInstance(FIRE_GUID, LotTilePos.FromBigTile(fpos.TileX, fpos.TileY, fpos.Level), Direction.NORTH); fires[index] = true; } } } } return(madeAFire?VMPrimitiveExitCode.GOTO_TRUE:VMPrimitiveExitCode.GOTO_FALSE); }
public List <VMObstacle> GenerateRoomObs(ushort room, sbyte level, Rectangle bounds, VMContext context) { var result = new List <VMObstacle>(); if (room == 0) { bounds = new Rectangle(1, 1, Width - 2, Height - 2); } var x1 = Math.Max(0, bounds.X - 1); var x2 = Math.Min(Width, bounds.Right + 1); var y1 = Math.Max(0, bounds.Y - 1); var y2 = Math.Min(Height, bounds.Bottom + 1); for (int y = y1; y < y2; y++) { VMObstacle next = null; for (int x = x1; x < x2; x++) { uint tRoom = Map[x + y * Width]; if ((ushort)tRoom != room && ((tRoom >> 16) & 0x7FFF) != room) { //is there a door on this tile? var door = (context.ObjectQueries.GetObjectsAt(LotTilePos.FromBigTile((short)x, (short)y, level))?.FirstOrDefault( o => ((VMEntityFlags2)(o.GetValue(VMStackObjectVariable.FlagField2)) & VMEntityFlags2.ArchitectualDoor) > 0) ); if (door != null) { //ok... is is a portal to this room? block all sides that are not a portal to this room var otherSide = door.MultitileGroup.Objects.FirstOrDefault(o => context.GetObjectRoom(o) == room && o.EntryPoints[15].ActionFunction != 0); if (otherSide != null) { //make a hole for this door if (next != null) { next = null; } // note: the sims 1 stops here. this creates issues where sims can walk through doors in some circumstance // eg. two doors back to back into the same room. The sim will not perform a room route to the middle room, they will just walk through the door. // like, through it. This also works for pools but some additional rules prevent you from doing anything too silly. // we want to create 1 unit thick walls blocking each non-portal side. // todo: fix for this continue; } } if (next != null) { next.x2 += 16; } else { next = new VMObstacle((x << 4) - 3, (y << 4) - 3, (x << 4) + 19, (y << 4) + 19); result.Add(next); } } else { if (next != null) { next = null; } } } } OptimizeObstacles(result); return(result); }
public override VMPrimitiveExitCode Execute(VMStackFrame context, VMPrimitiveOperand args) { var operand = (VMFindLocationForOperand)args; var refObj = (operand.UseLocalAsRef) ? context.VM.GetObjectById(context.Locals[operand.Local]) : context.Caller; var obj = context.StackObject; var flags = VMPlaceRequestFlags.AcceptSlots; if (operand.UserEditableTilesOnly) { flags |= VMPlaceRequestFlags.UserBuildableLimit; } if (operand.AllowIntersection && operand.Mode != 4 && operand.Mode != 3) { flags |= VMPlaceRequestFlags.AllowIntersection; } switch (operand.Mode) { case 0: //default if (FindLocationFor(obj, refObj, context.VM.Context, flags)) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } case 1: //out of world obj.SetPosition(LotTilePos.OUT_OF_WORLD, Direction.NORTH, context.VM.Context, flags); return(VMPrimitiveExitCode.GOTO_TRUE); case 2: //"smoke cloud" - halfway between callee and caller (is "caller" actually reference object?) var smokePos = context.Callee.Position; smokePos += context.Caller.Position; smokePos /= 2; smokePos -= new LotTilePos(8, 8, 0); //smoke is 2x2... offset to center it. return((obj.SetPosition(smokePos, Direction.NORTH, context.VM.Context).Status == VMPlacementError.Success)? VMPrimitiveExitCode.GOTO_TRUE : VMPrimitiveExitCode.GOTO_FALSE); case 3: case 4: //along object vector var intDir = (int)Math.Round(Math.Log((double)refObj.Direction, 2)); if (operand.Mode == 4) { intDir = (intDir + 2) % 8; //lateral to object vector } if (FindLocationVector(obj, refObj, context.VM.Context, intDir, flags)) { return(VMPrimitiveExitCode.GOTO_TRUE); } else { return(VMPrimitiveExitCode.GOTO_FALSE); } case 5: //random var ctx = context.VM.Context; for (int i = 0; i < 100; i++) { var loc = LotTilePos.FromBigTile((short)(ctx.NextRandom((ulong)ctx.Architecture.Width - 2) + 1), (short)(ctx.NextRandom((ulong)ctx.Architecture.Height - 2) + 1), refObj.Position.Level); if (obj.SetPosition(loc, Direction.NORTH, ctx, flags).Status == VMPlacementError.Success) { return(VMPrimitiveExitCode.GOTO_TRUE); } } return(VMPrimitiveExitCode.GOTO_FALSE); } return(VMPrimitiveExitCode.GOTO_FALSE); }
public void SubmitCommand(string msg) { var state = LastState; if (state == null) { return; } var spaceIndex = msg.IndexOf(' '); if (spaceIndex == -1) { spaceIndex = msg.Length; } var cmd = msg.Substring(1, spaceIndex - 1); var args = msg.Substring(Math.Min(msg.Length, spaceIndex + 1), Math.Max(0, msg.Length - (spaceIndex + 1))); string response = "(" + msg + ") "; var tilePos = vm.Context.World.EstTileAtPosWithScroll(Control.GetScaledPoint(state.MouseState.Position).ToVector2() / FSOEnvironment.DPIScaleFactor); try { switch (cmd.ToLowerInvariant()) { case "roomat": //!roomat LotTilePos targetrPos = new LotTilePos((short)(tilePos.X * 16), (short)(tilePos.Y * 16), vm.Context.World.State.Level); var room = vm.Context.GetRoomAt(targetrPos); response += "Room at (" + targetrPos.TileX + ", " + targetrPos.TileY + ", " + targetrPos.Level + ") is " + room + "\r\n"; var roomInfo = vm.Context.RoomInfo[room]; foreach (var obj in roomInfo.Room.AdjRooms) { var info = vm.Context.RoomInfo[obj]; response += "adjacent room: " + obj; response += "\r\n"; } break; case "objat": //!objat (objects at mouse position) LotTilePos targetPos = LotTilePos.FromBigTile((short)tilePos.X, (short)tilePos.Y, vm.Context.World.State.Level); if (args == "oow") { targetPos = LotTilePos.OUT_OF_WORLD; } var objs = vm.Context.ObjectQueries.GetObjectsAt(targetPos); response += "Objects at (" + targetPos.TileX + ", " + targetPos.TileY + ", " + targetPos.Level + ")\r\n"; foreach (var obj in objs) { response += ObjectSummary(obj); response += "\r\n"; } break; case "del": //!del objectID vm.SendCommand(new VMNetDeleteObjectCmd() { ObjectID = short.Parse(args), CleanupAll = true }); response += "Sent deletion command."; break; default: response += "Unknown command."; break; } } catch (Exception e) { response += "Bad command."; } vm.SignalChatEvent(new VMChatEvent(null, VMChatEventType.Generic, response)); }
public void ShowPieMenu(Point pt, UpdateState state) { if (!LiveMode) { /* * if (CustomControl != null) CustomControl.MouseDown(state); * else ObjectHolder.MouseDown(state); */ if (FSOEnvironment.SoftwareKeyboard && ObjectHolder.Holding == null) { ObjectHolder.MouseDown(state); } return; } if (PieMenu == null && ActiveEntity != null) { VMEntity obj; //get new pie menu, make new pie menu panel for it var tilePos = World.EstTileAtPosWithScroll(new Vector2(pt.X, pt.Y) / FSOEnvironment.DPIScaleFactor); LotTilePos targetPos = LotTilePos.FromBigTile((short)tilePos.X, (short)tilePos.Y, World.State.Level); if (vm.Context.SolidToAvatars(targetPos).Solid) { targetPos = LotTilePos.OUT_OF_WORLD; } GotoObject.SetPosition(targetPos, Direction.NORTH, vm.Context); var newHover = World.GetObjectIDAtScreenPos(pt.X, pt.Y, GameFacade.GraphicsDevice); ObjectHover = newHover; bool objSelected = ObjectHover > 0; if (objSelected || (GotoObject.Position != LotTilePos.OUT_OF_WORLD && ObjectHover <= 0)) { if (objSelected) { obj = vm.GetObjectById(ObjectHover); } else { obj = GotoObject; } if (obj != null) { obj = obj.MultitileGroup.GetInteractionGroupLeader(obj); if (obj is VMGameObject && ((VMGameObject)obj).Disabled > 0) { var flags = ((VMGameObject)obj).Disabled; if ((flags & VMGameObjectDisableFlags.ForSale) > 0) { //for sale var retailPrice = obj.MultitileGroup.Price; //wrong... should get this from catalog var salePrice = obj.MultitileGroup.SalePrice; ShowErrorTooltip(state, 22, true, "$" + retailPrice.ToString("##,#0"), "$" + salePrice.ToString("##,#0")); } else if ((flags & VMGameObjectDisableFlags.LotCategoryWrong) > 0) { ShowErrorTooltip(state, 21, true); //category wrong } else if ((flags & VMGameObjectDisableFlags.TransactionIncomplete) > 0) { ShowErrorTooltip(state, 27, true); //transaction not yet complete } else if ((flags & VMGameObjectDisableFlags.ObjectLimitExceeded) > 0) { ShowErrorTooltip(state, 24, true); //object is temporarily disabled... todo: something more helpful } else if ((flags & VMGameObjectDisableFlags.PendingRoommateDeletion) > 0) { ShowErrorTooltip(state, 16, true); //pending roommate deletion } } else { var menu = obj.GetPieMenu(vm, ActiveEntity, false, true); if (menu.Count != 0) { HITVM.Get().PlaySoundEvent(UISounds.PieMenuAppear); PieMenu = new UIPieMenu(menu, obj, ActiveEntity, this); this.Add(PieMenu); PieMenu.X = state.MouseState.X / FSOEnvironment.DPIScaleFactor; PieMenu.Y = state.MouseState.Y / FSOEnvironment.DPIScaleFactor; PieMenu.UpdateHeadPosition(state.MouseState.X, state.MouseState.Y); } } } } else { ShowErrorTooltip(state, 0, true); } } else { if (PieMenu != null) { PieMenu.RemoveSimScene(); } this.Remove(PieMenu); PieMenu = null; } }
private void UpdateCutaway(UpdateState state) { if (vm.Context.Blueprint != null) { World.State.DynamicCutaway = (WallsMode == 1); //first we need to cycle the rooms that are being cutaway. Keep this up even if we're in all-cut mode. var mouseTilePos = World.EstTileAtPosWithScroll(new Vector2(state.MouseState.X, state.MouseState.Y) / FSOEnvironment.DPIScaleFactor); var roomHover = vm.Context.GetRoomAt(LotTilePos.FromBigTile((short)(mouseTilePos.X), (short)(mouseTilePos.Y), World.State.Level)); var outside = (vm.Context.RoomInfo[roomHover].Room.IsOutside); if (!outside && !CutRooms.Contains(roomHover)) { CutRooms.Add(roomHover); //outside hover should not persist like with other rooms. } while (CutRooms.Count > 3) { CutRooms.Remove(CutRooms.ElementAt(0)); } if (LastWallMode != WallsMode) { if (WallsMode == 0) //walls down { LastCuts = new bool[vm.Context.Architecture.Width * vm.Context.Architecture.Height]; vm.Context.Blueprint.Cutaway = LastCuts; vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED)); for (int i = 0; i < LastCuts.Length; i++) { LastCuts[i] = true; } } else if (WallsMode == 1) { MouseCutRect = new Rectangle(); LastCutRooms = new HashSet <uint>() { uint.MaxValue }; //must regenerate cuts } else //walls up or roof { LastCuts = new bool[vm.Context.Architecture.Width * vm.Context.Architecture.Height]; vm.Context.Blueprint.Cutaway = LastCuts; vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED)); } LastWallMode = WallsMode; } if (WallsMode == 1) { HashSet <uint> finalRooms; int recut = 0; if (FSOEnvironment.SoftwareKeyboard) { finalRooms = new HashSet <uint>(); foreach (var room in vm.Context.RoomInfo) { if (!room.Room.IsOutside && room.Room.Floor == World.State.Level - 1) { finalRooms.Add(room.Room.RoomID); } } } else { if (RMBScroll || !MouseIsOn) { return; } finalRooms = new HashSet <uint>(CutRooms); var newCut = new Rectangle((int)(mouseTilePos.X - 2.5), (int)(mouseTilePos.Y - 2.5), 5, 5); newCut.X -= VMArchitectureTools.CutCheckDir[(int)World.State.CutRotation][0] * 2; newCut.Y -= VMArchitectureTools.CutCheckDir[(int)World.State.CutRotation][1] * 2; if (newCut != MouseCutRect) { MouseCutRect = newCut; recut = 1; } } if (LastFloor != World.State.Level || LastRotation != World.State.CutRotation || !finalRooms.SetEquals(LastCutRooms)) { LastCuts = VMArchitectureTools.GenerateRoomCut(vm.Context.Architecture, World.State.Level, World.State.CutRotation, finalRooms); recut = 2; LastFloor = World.State.Level; LastRotation = World.State.CutRotation; } LastCutRooms = finalRooms; if (recut > 0) { var finalCut = new bool[LastCuts.Length]; Array.Copy(LastCuts, finalCut, LastCuts.Length); var notableChange = VMArchitectureTools.ApplyCutRectangle(vm.Context.Architecture, World.State.Level, finalCut, MouseCutRect); if (recut > 1 || notableChange || LastRectCutNotable) { vm.Context.Blueprint.Cutaway = finalCut; vm.Context.Blueprint.Damage.Add(new FSO.LotView.Model.BlueprintDamage(FSO.LotView.Model.BlueprintDamageType.WALL_CUT_CHANGED)); } LastRectCutNotable = notableChange; } } } }
public void SetFamilyMember(int index) { if (RepresentFamily.Count <= index) { var member = (VMAvatar)vm.Context.CreateObjectInstance(0x7FD96B54, LotTilePos.OUT_OF_WORLD , Direction.EAST, false).BaseObject; RepresentFamily.Add(member); } var fam = RepresentFamily[index]; fam.SetPosition(LotTilePos.FromBigTile(34, 31, 1) + new LotTilePos((short)((((index + 1) / 2) % 2) * 8), (short)(((index % 2) * 2 - 1) * ((index + 1) / 2) * 10), 0), Direction.EAST, vm.Context, VMPlaceRequestFlags.AllowIntersection); var data = WIPFamily[index]; //set this person's body and head fam.Name = data.Name; fam.Avatar.Skeleton = Content.Get().AvatarSkeletons.Get((data.Gender > 1) ? "child.skel" : "adult.skel").Clone(); fam.Avatar.BaseSkeleton = fam.Avatar.Skeleton.Clone(); fam.Avatar.ReloadSkeleton(); fam.SetPersonData(VMPersonDataVariable.PersonsAge, (short)((data.Gender > 1) ? 12 : 21)); fam.InitBodyData(vm.Context); var oft = new Outfit() { TS1AppearanceID = data.Body + ".apr", TS1TextureID = data.BodyTex }; var code = (data.Gender > 1) ? "u" : ((data.Gender == 0) ? "m" : "f"); var hg = data.HandgroupTex; oft.LiteralHandgroup = new HandGroup() { TS1HandSet = true, LightSkin = new HandSet() { LeftHand = new Hand() { Idle = new Gesture() { Name = "h" + code + "lo.apr", TexName = "huao" + hg }, Pointing = new Gesture() { Name = "h" + code + "lp.apr", TexName = "huap" + hg }, Fist = new Gesture() { Name = "h" + code + "lc.apr", TexName = "huac" + hg } }, RightHand = new Hand() { Idle = new Gesture() { Name = "h" + code + "ro.apr", TexName = "huao" + hg }, Pointing = new Gesture() { Name = "h" + code + "rp.apr", TexName = "huap" + hg }, Fist = new Gesture() { Name = "h" + code + "rc.apr", TexName = "huac" + hg } } } }; fam.BodyOutfit = new FSO.SimAntics.Model.VMOutfitReference(oft); fam.HeadOutfit = new FSO.SimAntics.Model.VMOutfitReference(new Outfit() { TS1AppearanceID = data.Head + ".apr", TS1TextureID = data.HeadTex }); }
private void UpdateCarousel(UpdateState state) { var frac = 60f / FSOEnvironment.RefreshRate; var minSpeed = (Math.PI / 240f) * frac; var mult = (float)Math.Pow(0.95, frac); var moving = 0; if (state.MouseStates.Count > 0) { if (XLast == -1) { if (state.MouseState.Y > 282) { XLast = state.MouseState.X; } } else { if (state.MouseState.Y / (float)UIScreen.Current.ScreenHeight > 0.625f) { BodySpeed = ((XLast - state.MouseState.X) / 200f) * frac; moving = 1; } else { HeadSpeed = ((XLast - state.MouseState.X) / 200f) * frac; moving = 2; } XLast = state.MouseState.X; } } else { XLast = -1; } BodySpeed = BodySpeed * mult; if (Math.Abs(BodySpeed) < minSpeed && moving != 1) { var targInt = (int)Math.Round(BodyPosition); BodySpeed = (float)Math.Max(-minSpeed, Math.Min(minSpeed, targInt - BodyPosition)); } HeadSpeed = HeadSpeed * mult; if (Math.Abs(HeadSpeed) < minSpeed && moving != 2) { var targInt = (int)Math.Round(HeadPosition); HeadSpeed = (float)Math.Max(-minSpeed, Math.Min(minSpeed, targInt - HeadPosition)); } HeadPosition += HeadSpeed; BodyPosition += BodySpeed; var room = vm.Context.GetRoomAt(LotTilePos.FromBigTile(28, 21, 1)); foreach (var body in BodyAvatars) { body.SetRoom(room); } foreach (var head in HeadAvatars) { head.SetRoom(65534); } var curbody = (int)BodyPosition; if (curbody != BodyPositionLast) { FSO.HIT.HITVM.Get().PlaySoundEvent(FSO.Client.UI.Model.UISounds.Click); int replacePos = (int)DirectionUtils.PosMod((-BodyPositionLast), 18); int increment = 1; if (curbody < BodyPositionLast) //start adding after last position's compliment position { increment = -1; replacePos = (int)DirectionUtils.PosMod((-BodyPositionLast), 18); } var total = Math.Abs(curbody - BodyPositionLast); for (int i = 0; i < total; i++) { if (increment == -1) { SetBody(BodyAvatars[replacePos], BodyPositionLast - 1); } else { SetBody(BodyAvatars[replacePos], BodyPositionLast + 17); } BodyPositionLast += increment; replacePos = ((replacePos - increment) + 18) % 18; } BodyPositionLast = curbody; } var curhead = (int)HeadPosition; if (curhead != HeadPositionLast) { FSO.HIT.HITVM.Get().PlaySoundEvent(FSO.Client.UI.Model.UISounds.Click); int replacePos = (int)DirectionUtils.PosMod(-HeadPositionLast, 18); int increment = 1; if (curhead < HeadPositionLast) //start adding after last position's compliment position { increment = -1; replacePos = (int)DirectionUtils.PosMod((-HeadPositionLast), 18); } var total = Math.Abs(curhead - HeadPositionLast); for (int i = 0; i < total; i++) { if (increment == -1) { SetHead(HeadAvatars[replacePos], HeadPositionLast - 1); } else { SetHead(HeadAvatars[replacePos], HeadPositionLast + 17); } HeadPositionLast += increment; replacePos = ((replacePos - increment) + 18) % 18; } HeadPositionLast = curhead; } }