public GetObjPlace ( FSO.SimAntics.VMEntity target, FSO.LotView.Model.LotTilePos pos, Direction dir ) : |
||
target | FSO.SimAntics.VMEntity | |
pos | FSO.LotView.Model.LotTilePos | |
dir | Direction | |
return |
public VMPlacementResult GetObjPlace(VMEntity target, LotTilePos pos, Direction dir)
{
//ok, this might be confusing...
short allowedHeights = target.GetValue(VMStackObjectVariable.AllowedHeightFlags);
short weight = target.GetValue(VMStackObjectVariable.Weight);
bool noFloor = (allowedHeights&1)==0;
var flags = (VMEntityFlags)target.GetValue(VMStackObjectVariable.Flags);
bool allowAvatars = ((flags & VMEntityFlags.DisallowPersonIntersection) == 0) && ((flags & VMEntityFlags.AllowPersonIntersection) > 0);
VMObstacle footprint = target.GetObstacle(pos, dir);
ushort room = GetRoomAt(pos);
VMPlacementError status = (noFloor)?VMPlacementError.HeightNotAllowed:VMPlacementError.Success;
VMEntity statusObj = null;
if (footprint == null || pos.Level < 1)
{
return new VMPlacementResult { Status = status };
}
var objs = RoomInfo[room].Entities;
foreach (var obj in objs)
{
if (obj.MultitileGroup == target.MultitileGroup || (obj is VMAvatar && allowAvatars)
|| (target.GhostImage && target.GhostOriginal != null && target.GhostOriginal.Objects.Contains(obj))) continue;
var oFoot = obj.Footprint;
if (oFoot != null && oFoot.Intersects(footprint)
&& (!(target.ExecuteEntryPoint(5, this, true, obj, new short[] { obj.ObjectID, 0, 0, 0 })
|| obj.ExecuteEntryPoint(5, this, true, target, new short[] { target.ObjectID, 0, 0, 0 })))
)
{
statusObj = obj;
status = VMPlacementError.CantIntersectOtherObjects;
//this object is technically solid. Check if we can place on top of it
if (allowedHeights>1 && obj.TotalSlots() > 0 && (obj.GetSlot(0) == null || obj.GetSlot(0) == target))
{
//first check if we have a slot 0, which is what we place onto. then check if it's empty,
//then check if the object can support this one's weight.
//we also need to make sure that the height of this specific slot is allowed.
if (((1 << (obj.GetSlotHeight(0) - 1)) & allowedHeights) > 0)
{
if (weight < obj.GetValue(VMStackObjectVariable.SupportStrength))
{
return new VMPlacementResult(VMPlacementError.Success, obj);
}
else
{
status = VMPlacementError.CantSupportWeight;
}
}
else
{
if (noFloor)
{
if ((allowedHeights & (1 << 3)) > 0) status = VMPlacementError.CounterHeight;
else status = (obj.GetSlotHeight(0) == 8) ? VMPlacementError.CannotPlaceComputerOnEndTable : VMPlacementError.HeightNotAllowed;
}
}
}
}
}
return new VMPlacementResult(status, statusObj);
}
public VMPlacementResult PositionValid(LotTilePos pos,Direction direction,VMContext context) { if (pos == LotTilePos.OUT_OF_WORLD) { return(new VMPlacementResult()); } else if (context.IsOutOfBounds(pos)) { return new VMPlacementResult { Status = VMPlacementError.LocationOutOfBounds } } ; //TODO: speedup with exit early checks //TODO: corner checks (wtf uses this) var arch = context.Architecture; var wall = arch.GetWall(pos.TileX,pos.TileY,pos.Level); //todo: preprocess to check which walls are real solid walls and not fences. if (this is VMGameObject) //needs special handling for avatar eventually { VMPlacementError wallValid = WallChangeValid(wall,direction,true); if (wallValid != VMPlacementError.Success) { return new VMPlacementResult { Status = wallValid } } ; } var floor = arch.GetFloor(pos.TileX,pos.TileY,pos.Level); VMPlacementError floorValid = FloorChangeValid(floor,pos.Level); if (floorValid != VMPlacementError.Success) { return new VMPlacementResult { Status = floorValid } } ; //we've passed the wall test, now check if we intersect any objects. var valid = (this is VMAvatar)? context.GetAvatarPlace(this,pos,direction) : context.GetObjPlace(this,pos,direction); return(valid); }