diff --git a/TSOClient/FSO.Server/Servers/Lot/Domain/LotContainer.cs b/TSOClient/FSO.Server/Servers/Lot/Domain/LotContainer.cs index 07d5587f8..160ff4374 100644 --- a/TSOClient/FSO.Server/Servers/Lot/Domain/LotContainer.cs +++ b/TSOClient/FSO.Server/Servers/Lot/Domain/LotContainer.cs @@ -108,6 +108,8 @@ public class LotContainer 0x50907E06, //flies - controller 0x3161BB5B, //job controller + 0x475CC813, //water balloon controller + 0x5157DDF2, //cat carrier 0x3278BD34, //dog carrier }; diff --git a/TSOClient/tso.client/UI/Panels/UILotControl.cs b/TSOClient/tso.client/UI/Panels/UILotControl.cs index e6b19880e..7d01cf940 100644 --- a/TSOClient/tso.client/UI/Panels/UILotControl.cs +++ b/TSOClient/tso.client/UI/Panels/UILotControl.cs @@ -422,6 +422,18 @@ private void OnMouse(UIMouseEventType type, UpdateState state) } } + private short GetFloorBlockableHover(Point pt) + { + var tilePos = World.EstTileAtPosWithScroll3D(new Vector2(pt.X, pt.Y) / FSOEnvironment.DPIScaleFactor); + var newHover = World.GetObjectIDAtScreenPos(pt.X, + pt.Y, + GameFacade.GraphicsDevice); + + var hobj = vm.GetObjectById(newHover); + if (hobj == null || hobj.Position.Level < tilePos.Z) newHover = 0; + return newHover; + } + public void Click(Point pt, UpdateState state) { if (!LiveMode) @@ -434,9 +446,9 @@ public void Click(Point pt, UpdateState state) { 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); + var tilePos = World.EstTileAtPosWithScroll3D(new Vector2(pt.X, pt.Y) / FSOEnvironment.DPIScaleFactor); - LotTilePos targetPos = LotTilePos.FromBigTile((short)tilePos.X, (short)tilePos.Y, World.State.Level); + LotTilePos targetPos = LotTilePos.FromBigTile((short)tilePos.X, (short)tilePos.Y, (sbyte)tilePos.Z); if (vm.Context.SolidToAvatars(targetPos).Solid) targetPos = LotTilePos.OUT_OF_WORLD; GotoObject.SetPosition(targetPos, Direction.NORTH, vm.Context); @@ -445,6 +457,8 @@ public void Click(Point pt, UpdateState state) pt.Y, GameFacade.GraphicsDevice); + var hobj = vm.GetObjectById(newHover); + if (hobj == null || hobj.Position.Level < tilePos.Z) newHover = 0; ObjectHover = newHover; bool objSelected = ObjectHover > 0; @@ -574,9 +588,7 @@ public void LiveModeUpdate(UpdateState state, bool scrolled) OldMX = state.MouseState.X; OldMY = state.MouseState.Y; var scaled = GetScaledPoint(state.MouseState.Position); - var newHover = World.GetObjectIDAtScreenPos(scaled.X, - scaled.Y, - GameFacade.GraphicsDevice); + var newHover = GetFloorBlockableHover(scaled); if (ObjectHover != newHover) { diff --git a/TSOClient/tso.client/UI/Panels/UIObjectHolder.cs b/TSOClient/tso.client/UI/Panels/UIObjectHolder.cs index 5859ec49c..9c382d2c9 100644 --- a/TSOClient/tso.client/UI/Panels/UIObjectHolder.cs +++ b/TSOClient/tso.client/UI/Panels/UIObjectHolder.cs @@ -49,6 +49,7 @@ public class UIObjectHolder //controls the object holder interface public bool Roommate; public bool DonateMode; + private bool Locked; public event HolderEventHandler OnPickup; public event HolderEventHandler OnDelete; @@ -131,7 +132,7 @@ public void MoveSelected(Vector2 pos, sbyte level) { for (int i = 0; i < 4; i++) { - status = Holding.Group.ChangePosition(LotTilePos.FromBigTile((short)pos.X, (short)pos.Y, World.State.Level), dir, vm.Context, VMPlaceRequestFlags.UserPlacement).Status; + 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)); } @@ -143,7 +144,7 @@ public void MoveSelected(Vector2 pos, sbyte level) 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) + (World.State.Level-1)*2.95f), + (((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); } @@ -152,7 +153,7 @@ public void MoveSelected(Vector2 pos, sbyte level) { var target = Holding.Group.Objects[i]; var tpos = target.VisualPosition; - tpos.Z = (World.State.Level - 1)*2.95f; + tpos.Z = (level - 1)*2.95f; Holding.CursorTiles[i].MultitileGroup.SetVisualPosition(tpos, Holding.Dir, vm.Context); } Holding.CanPlace = status; @@ -209,6 +210,37 @@ public void MouseDown(UpdateState state) } } + private void InventoryPlaceHolding() + { + var pos = Holding.Group.BaseObject.Position; + vm.SendCommand(new VMNetPlaceInventoryCmd + { + ObjectPID = Holding.InventoryPID, + dir = Holding.Dir, + level = pos.Level, + x = pos.x, + y = pos.y, + + Mode = (DonateMode) ? PurchaseMode.Donate : PurchaseMode.Normal + }); + } + + private void BuyHolding() + { + var pos = Holding.Group.BaseObject.Position; + var GUID = (Holding.Group.MultiTile) ? Holding.Group.BaseObject.MasterDefinition.GUID : Holding.Group.BaseObject.Object.OBJ.GUID; + vm.SendCommand(new VMNetBuyObjectCmd + { + GUID = GUID, + dir = Holding.Dir, + level = pos.Level, + x = pos.x, + y = pos.y, + + Mode = (DonateMode) ? PurchaseMode.Donate : PurchaseMode.Normal + }); + } + public void MouseUp(UpdateState state) { MouseIsDown = false; @@ -216,12 +248,13 @@ public void MouseUp(UpdateState state) { if (Holding.CanPlace == VMPlacementError.Success) { - HITVM.Get().PlaySoundEvent((Holding.IsBought) ? UISounds.ObjectMovePlace : UISounds.ObjectPlace); //ExecuteEntryPoint(11); //User Placement var putDown = Holding; var pos = Holding.Group.BaseObject.Position; + var badCategory = ((Holding.Group.BaseObject as VMGameObject)?.Disabled ?? 0).HasFlag(VMGameObjectDisableFlags.LotCategoryWrong); if (Holding.IsBought) { + HITVM.Get().PlaySoundEvent(UISounds.ObjectMovePlace); vm.SendCommand(new VMNetMoveObjectCmd { ObjectID = Holding.MoveTarget, @@ -231,32 +264,29 @@ public void MouseUp(UpdateState state) y = pos.y }); } - else if (Holding.InventoryPID > 0) - { - vm.SendCommand(new VMNetPlaceInventoryCmd + else { + if (badCategory) { - ObjectPID = Holding.InventoryPID, - dir = Holding.Dir, - level = pos.Level, - x = pos.x, - y = pos.y, - - Mode = (DonateMode) ? PurchaseMode.Donate : PurchaseMode.Normal - }); - } - else - { - var GUID = (Holding.Group.MultiTile)? Holding.Group.BaseObject.MasterDefinition.GUID : Holding.Group.BaseObject.Object.OBJ.GUID; - vm.SendCommand(new VMNetBuyObjectCmd + Locked = true; + UIAlert.YesNo(GameFacade.Strings.GetString("245", "5"), GameFacade.Strings.GetString("245", (Holding.InventoryPID > 0)?"7":"6"), true, + (confirm) => + { + Locked = false; + if (!confirm) return; + HITVM.Get().PlaySoundEvent(UISounds.ObjectPlace); + if (Holding.InventoryPID > 0) InventoryPlaceHolding(); + else BuyHolding(); + ClearSelected(); + if (OnPutDown != null) OnPutDown(putDown, state); //call this after so that buy mode etc can produce more. + }); + return; + } else { - GUID = GUID, - dir = Holding.Dir, - level = pos.Level, - x = pos.x, - y = pos.y, - - Mode = (DonateMode) ? PurchaseMode.Donate : PurchaseMode.Normal - }); + HITVM.Get().PlaySoundEvent(UISounds.ObjectPlace); + if (Holding.InventoryPID > 0) InventoryPlaceHolding(); + else BuyHolding(); + } + } ClearSelected(); if (OnPutDown != null) OnPutDown(putDown, state); //call this after so that buy mode etc can produce more. @@ -416,11 +446,24 @@ private Point GetScaledPoint(Point TapPoint) return ((TapPoint - screenMiddle).ToVector2() / World.BackbufferScale).ToPoint() + screenMiddle; } + private short GetFloorBlockableHover(Point pt) + { + var tilePos = World.EstTileAtPosWithScroll3D(new Vector2(pt.X, pt.Y) / FSOEnvironment.DPIScaleFactor); + var newHover = World.GetObjectIDAtScreenPos(pt.X, + pt.Y, + GameFacade.GraphicsDevice); + + var hobj = vm.GetObjectById(newHover); + if (hobj == null || hobj.Position.Level < tilePos.Z) newHover = 0; + return newHover; + } + public void Update(UpdateState state, bool scrolled) { LastState = state; if (ShowTooltip) state.UIState.TooltipProperties.UpdateDead = false; MouseClicked = (MouseIsDown && (!MouseWasDown)); + if (Locked) return; CursorType cur = CursorType.SimsMove; if (Holding != null) @@ -455,8 +498,8 @@ public void Update(UpdateState state, bool scrolled) cur = CursorType.SimsRotate; if (Math.Sqrt(xDiff * xDiff + yDiff * yDiff) > 64) { - var from = World.EstTileAtPosWithScroll(new Vector2(MouseDownX, MouseDownY)); - var target = World.EstTileAtPosWithScroll(state.MouseState.Position.ToVector2()); + var from = World.EstTileAtPosWithScroll(new Vector2(MouseDownX, MouseDownY), Holding.Level); + var target = World.EstTileAtPosWithScroll(state.MouseState.Position.ToVector2(), Holding.Level); var vec = target - from; var dir = Math.Atan2(vec.Y, vec.X); @@ -503,15 +546,15 @@ public void Update(UpdateState state, bool scrolled) else { var scaled = GetScaledPoint(state.MouseState.Position); - var tilePos = World.EstTileAtPosWithScroll(new Vector2(scaled.X, scaled.Y) / FSOEnvironment.DPIScaleFactor) + Holding.TilePosOffset; - MoveSelected(tilePos, 1); + var tilePos = World.EstTileAtPosWithScroll3D(new Vector2(scaled.X, scaled.Y) / FSOEnvironment.DPIScaleFactor + Holding.MousePosOffset); + MoveSelected(new Vector2(tilePos.X, tilePos.Y), (sbyte)tilePos.Z); // + Holding.TilePosOffset } } else if (MouseClicked) { //not holding an object, but one can be selected var scaled = GetScaledPoint(state.MouseState.Position); - var newHover = World.GetObjectIDAtScreenPos(scaled.X, scaled.Y, GameFacade.GraphicsDevice); + var newHover = GetFloorBlockableHover(scaled); //World.GetObjectIDAtScreenPos(scaled.X, scaled.Y, GameFacade.GraphicsDevice); if (MouseClicked && (newHover != 0) && (vm.GetObjectById(newHover) is VMGameObject)) { var objGroup = vm.GetObjectById(newHover).MultitileGroup; @@ -519,7 +562,7 @@ public void Update(UpdateState state, bool scrolled) var allowMove = vm.PlatformState.Validator.CanMoveObject((VMAvatar)ParentControl.ActiveEntity, objGroup.BaseObject); var success = (Roommate || objGroup.SalePrice > -1)?objGroup.BaseObject.IsUserMovable(vm.Context, false): VMPlacementError.ObjectNotOwnedByYou; if (GameFacade.EnableMod) success = VMPlacementError.Success; - if (objBasePos.Level != World.State.Level) success = VMPlacementError.CantEffectFirstLevelFromSecondLevel; + //if (objBasePos.Level != World.State.Level) success = VMPlacementError.CantEffectFirstLevelFromSecondLevel; if (success == VMPlacementError.Success) { var ghostGroup = vm.Context.GhostCopyGroup(objGroup); @@ -533,6 +576,7 @@ public void Update(UpdateState state, bool scrolled) Holding.CanDelete = canDelete; Holding.DeleteError = canDelete ? VMPlacementError.CannotDeleteObject : VMPlacementError.ObjectNotOwnedByYou; Holding.MoveTarget = newHover; + Holding.MousePosOffset = (objGroup.BaseObject.WorldUI.GetScreenPos(World.State) - GetScaledPoint(state.MouseState.Position).ToVector2()) / FSOEnvironment.DPIScaleFactor; Holding.TilePosOffset = new Vector2(objBasePos.x / 16f, objBasePos.y / 16f) - World.EstTileAtPosWithScroll(GetScaledPoint(state.MouseState.Position).ToVector2() / FSOEnvironment.DPIScaleFactor); if (OnPickup != null) OnPickup(Holding, state); //ExecuteEntryPoint(12); //User Pickup @@ -578,6 +622,7 @@ public class UIObjectSelection public Direction Dir = Direction.NORTH; public Vector2 TilePos; public Vector2 TilePosOffset; + public Vector2 MousePosOffset; public bool Clicked; public VMPlacementError CanPlace; public sbyte Level; diff --git a/TSOClient/tso.client/UI/Panels/UIQueryPanel.cs b/TSOClient/tso.client/UI/Panels/UIQueryPanel.cs index cf00e5efa..4a34ec09b 100644 --- a/TSOClient/tso.client/UI/Panels/UIQueryPanel.cs +++ b/TSOClient/tso.client/UI/Panels/UIQueryPanel.cs @@ -220,6 +220,7 @@ public int Tab } private string[] AdStrings; + private string[] CategoryStrings; private int _Mode; public int Mode @@ -263,6 +264,13 @@ public UIQueryPanel(UILotControl parent, LotView.World world) { AdStrings[i] = ((i<7)?str.Substring(0,str.Length-2)+"{0}":str) + "\r\n"; } + CategoryStrings = new string[11]; + for (int i = 0; i < 10; i++) + { + CategoryStrings[i] = GameFacade.Strings.GetString("f115", (i + 73).ToString()); + } + CategoryStrings[10] = GameFacade.Strings.GetString("f115", "98"); + var useSmall = (GlobalSettings.Default.GraphicsWidth < 1024) || FSOEnvironment.UIZoomFactor > 1f; var script = this.RenderScript("querypanel"+(useSmall?"":"1024")+".uis"); @@ -504,18 +512,25 @@ public void SetInfo(VM vm, VMEntity entity, bool bought) { motivesString.AppendFormat(GameFacade.Strings.GetString("206", "19") + "${0}\r\n", price); } - if (def.RatingHunger != 0) { motivesString.AppendFormat(AdStrings[0], def.RatingHunger); } - if (def.RatingComfort != 0) { motivesString.AppendFormat(AdStrings[1], def.RatingComfort); } - if (def.RatingHygiene != 0) { motivesString.AppendFormat(AdStrings[2], def.RatingHygiene); } - if (def.RatingBladder != 0) { motivesString.AppendFormat(AdStrings[3], def.RatingBladder); } - if (def.RatingEnergy != 0) { motivesString.AppendFormat(AdStrings[4], def.RatingEnergy); } - if (def.RatingFun != 0) { motivesString.AppendFormat(AdStrings[5], def.RatingFun); } - if (def.RatingRoom != 0) { motivesString.AppendFormat(AdStrings[6], def.RatingRoom); } + + var catFlags = def.LotCategories; + for (int i = 1; i < 12; i++) + { + if ((catFlags & (1 << i)) > 0) motivesString.AppendLine(CategoryStrings[i - 1]); + } + + if (def.RatingHunger != 0) { motivesString.AppendFormat(AdStrings[0], (short)def.RatingHunger); } + if (def.RatingComfort != 0) { motivesString.AppendFormat(AdStrings[1], (short)def.RatingComfort); } + if (def.RatingHygiene != 0) { motivesString.AppendFormat(AdStrings[2], (short)def.RatingHygiene); } + if (def.RatingBladder != 0) { motivesString.AppendFormat(AdStrings[3], (short)def.RatingBladder); } + if (def.RatingEnergy != 0) { motivesString.AppendFormat(AdStrings[4], (short)def.RatingEnergy); } + if (def.RatingFun != 0) { motivesString.AppendFormat(AdStrings[5], (short)def.RatingFun); } + if (def.RatingRoom != 0) { motivesString.AppendFormat(AdStrings[6], (short)def.RatingRoom); } var sFlags = def.RatingSkillFlags; for (int i = 0; i < 7; i++) { - if ((sFlags & (1 << i)) > 0) motivesString.Append(AdStrings[i+7]); + if ((sFlags & (1 << i)) > 0) motivesString.Append(AdStrings[i + 7]); } MotivesText.CurrentText = motivesString.ToString(); diff --git a/TSOClient/tso.content/Content/Objects/Casino_2-Tile_Bar_CC.iff b/TSOClient/tso.content/Content/Objects/Casino_2-Tile_Bar_CC.iff index 6c5b521f7..1c49e5403 100644 Binary files a/TSOClient/tso.content/Content/Objects/Casino_2-Tile_Bar_CC.iff and b/TSOClient/tso.content/Content/Objects/Casino_2-Tile_Bar_CC.iff differ diff --git a/TSOClient/tso.content/Content/UI/uitext/english.dir/_f115_neighpagestrings.cst b/TSOClient/tso.content/Content/UI/uitext/english.dir/_f115_neighpagestrings.cst index 0bd8b043a..53c65af14 100644 --- a/TSOClient/tso.content/Content/UI/uitext/english.dir/_f115_neighpagestrings.cst +++ b/TSOClient/tso.content/Content/UI/uitext/english.dir/_f115_neighpagestrings.cst @@ -137,4 +137,6 @@ You can only place a Town Hall within the neighborhood you are Mayor of, and you 94 ^Click to view this Rating^ 95 ^Click to view all Ratings^ 96 ^%s Ratings^ -97 ^Your rating has been recorded. Thank you for your input! (if you already had a rating for this mayor, your new rating replaced it)^ \ No newline at end of file +97 ^Your rating has been recorded. Thank you for your input! (if you already had a rating for this mayor, your new rating replaced it)^ + +98 ^Community^ \ No newline at end of file diff --git a/TSOClient/tso.world/RC/World2DRC.cs b/TSOClient/tso.world/RC/World2DRC.cs index 5aa4f6396..701ab58ae 100644 --- a/TSOClient/tso.world/RC/World2DRC.cs +++ b/TSOClient/tso.world/RC/World2DRC.cs @@ -242,7 +242,7 @@ public override short GetObjectIDAtScreenPos(int x, int y, GraphicsDevice gd, Wo float bestDistance = float.MaxValue; foreach (var obj in Blueprint.Objects) { - if (obj.Level != state.Level || !obj.Visible || obj.CutawayHidden) continue; + if (obj.Level > state.Level || !obj.Visible || obj.CutawayHidden) continue; var objR = (ObjectComponentRC)obj; var intr = objR.IntersectsBounds(ray); if (obj.Container != null && intr != null) intr = intr.Value - 1.5f; @@ -255,7 +255,7 @@ public override short GetObjectIDAtScreenPos(int x, int y, GraphicsDevice gd, Wo foreach (var sim in Blueprint.Avatars) { - if (!sim.Visible) continue; + if (!sim.Visible || sim.Level > state.Level) continue; var pos = sim.GetPelvisPosition()*3; pos = new Vector3(pos.X, pos.Z, pos.Y) + new Vector3(1.5f, 0, 1.5f); var box = new BoundingBox(pos - new Vector3(0.5f, 2, 0.5f), pos + new Vector3(0.5f, 2, 0.5f)); diff --git a/TSOClient/tso.world/World.cs b/TSOClient/tso.world/World.cs index cd9b9e3d9..92e9b6d9c 100644 --- a/TSOClient/tso.world/World.cs +++ b/TSOClient/tso.world/World.cs @@ -653,11 +653,12 @@ public void Force2DPredraw(GraphicsDevice device) return tMin; } - public Vector2 EstTileAtPosWithScroll(Vector2 pos) + public Vector2 EstTileAtPosWithScroll(Vector2 pos, sbyte level = -1) { + if (level == -1) level = State.Level; pos *= new Vector2(FSOEnvironment.DPIScaleFactor); var sPos = new Vector3(pos, 0); - + var p1 = State.Device.Viewport.Unproject(sPos, State.Camera.Projection, State.Camera.View, Matrix.Identity); sPos.Z = 1; var p2 = State.Device.Viewport.Unproject(sPos, State.Camera.Projection, State.Camera.View, Matrix.Identity); @@ -665,9 +666,9 @@ public Vector2 EstTileAtPosWithScroll(Vector2 pos) dir.Normalize(); var ray = new Ray(p1, p2 - p1); ray.Direction.Normalize(); - ray.Position -= new Vector3(0, (State.Level-1) * 2.95f * 3, 0); - - var baseBox = new BoundingBox(new Vector3(0, -5000, 0), new Vector3(Blueprint.Width*3, 5000, Blueprint.Height*3)); + ray.Position -= new Vector3(0, (level - 1) * 2.95f * 3, 0); + + var baseBox = new BoundingBox(new Vector3(0, -5000, 0), new Vector3(Blueprint.Width * 3, 5000, Blueprint.Height * 3)); if (baseBox.Contains(ray.Position) != ContainmentType.Contains) { //move ray start inside box @@ -685,15 +686,15 @@ public Vector2 EstTileAtPosWithScroll(Vector2 pos) var py = (ray.Direction.Z > 0); int iteration = 0; - while (mx >= 0 && mx < Blueprint.Width && my >= 0 && my= 0 && mx < Blueprint.Width && my >= 0 && my < Blueprint.Width) { //test triangle 1. (centre of tile down xz, we lean towards positive x) var plane = new Plane( - new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my) * Blueprint.TerrainFactor*3, my * 3), - new Vector3(mx * 3+3, Blueprint.GetAltPoint(mx+1, my) * Blueprint.TerrainFactor*3, my * 3), - new Vector3(mx * 3+3, Blueprint.GetAltPoint(mx+1, my+1) * Blueprint.TerrainFactor*3, my * 3+3) + new Vector3(mx * 3, Blueprint.GetAltPoint(mx, my) * Blueprint.TerrainFactor * 3, my * 3), + new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my) * Blueprint.TerrainFactor * 3, my * 3), + new Vector3(mx * 3 + 3, Blueprint.GetAltPoint(mx + 1, my + 1) * Blueprint.TerrainFactor * 3, my * 3 + 3) ); - var tBounds = new BoundingBox(new Vector3(mx*3, -5000, my*3), new Vector3(mx*3+3, 5000, my*3+3)); + var tBounds = new BoundingBox(new Vector3(mx * 3, -5000, my * 3), new Vector3(mx * 3 + 3, 5000, my * 3 + 3)); var t1 = ray.Intersects(plane); var t2 = BoxRC2(ray, 3); @@ -705,11 +706,12 @@ public Vector2 EstTileAtPosWithScroll(Vector2 pos) var tentative = ray.Position + ray.Direction * (t1.Value + 0.00001f); //did it hit the correct side of the triangle? - var mySide = ((tentative.X / 3)%1) - ((tentative.Z / 3)%1); + var mySide = ((tentative.X / 3) % 1) - ((tentative.Z / 3) % 1); if (mySide >= 0) { return new Vector2(tentative.X / 3, tentative.Z / 3); - } else + } + else { //test the other side (positive z) plane = new Plane( @@ -749,6 +751,20 @@ public Vector2 EstTileAtPosWithScroll(Vector2 pos) return new Vector2(0, 0); } + public Vector3 EstTileAtPosWithScroll3D(Vector2 pos, sbyte startFloor = -1) + { + if (startFloor == -1) startFloor = State.Level; + for (sbyte floor = startFloor; floor > 0; floor--) + { + var result = EstTileAtPosWithScroll(pos, floor); + if (floor == 1 || (Blueprint.TileInbounds(result) && Blueprint.GetFloor((short)result.X, (short)result.Y, floor).Pattern != 0)) + { + return new Vector3(result, floor); + } + } + return new Vector3(EstTileAtPosWithScroll(pos), State.Level); + } + /// /// Gets the ID of the object at a given position. /// diff --git a/TSOClient/tso.world/World2D.cs b/TSOClient/tso.world/World2D.cs index 4af1738b5..0301877da 100644 --- a/TSOClient/tso.world/World2D.cs +++ b/TSOClient/tso.world/World2D.cs @@ -125,7 +125,7 @@ public virtual short GetObjectIDAtScreenPos(int x, int y, GraphicsDevice gd, Wor var tilePosition = obj.Position; - if (obj.Level != state.Level) continue; + if (obj.Level > state.Level) continue; var oPx = state.WorldSpace.GetScreenFromTile(tilePosition); obj.ValidateSprite(state); @@ -143,6 +143,7 @@ public virtual short GetObjectIDAtScreenPos(int x, int y, GraphicsDevice gd, Wor state._3D.Begin(gd); foreach (var avatar in Blueprint.Avatars) { + if (avatar.Level > state.Level) continue; _2d.OffsetPixel(state.WorldSpace.GetScreenFromTile(avatar.Position)); _2d.OffsetTile(avatar.Position); avatar.Draw(gd, state); diff --git a/TSOClient/tso.world/components/TerrainComponent.cs b/TSOClient/tso.world/components/TerrainComponent.cs index 3e3d98e4c..9679bc6ef 100644 --- a/TSOClient/tso.world/components/TerrainComponent.cs +++ b/TSOClient/tso.world/components/TerrainComponent.cs @@ -96,7 +96,10 @@ public void ForceSnow(bool toGrass) if (LightType == TerrainType.SNOW) { LightType = TerrainType.GRASS; - if (DarkType == TerrainType.SNOW) DarkType = TerrainType.GRASS; + } + if (DarkType == TerrainType.SNOW) + { + DarkType = TerrainType.GRASS; } } else diff --git a/TSOClient/tso.world/model/Blueprint.cs b/TSOClient/tso.world/model/Blueprint.cs index 7f996e5e8..ed576c715 100644 --- a/TSOClient/tso.world/model/Blueprint.cs +++ b/TSOClient/tso.world/model/Blueprint.cs @@ -299,6 +299,11 @@ public FloorTile GetFloor(short tileX, short tileY, sbyte level) return Floors[level-1][offset]; } + public bool TileInbounds(Vector2 tile) + { + return (tile.X >= 0 && tile.Y >= 0 && tile.X < Width && tile.Y < Height); + } + public void ChangeObjectLocation(ObjectComponent component, LotTilePos pos) { short tileX = (pos.x < 0) ? (short)0 : pos.TileX;