myspace / Lua /Dev /CoverDebug.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
22.1 kB
if Platform.cmdline then return end
MapVar("g_dbgCoversShown", false)
MapVar("s_CoversUpdateThread", false)
MapVar("s_CoversThreadBBox", false)
MapVar("s_Diff", false)
MapVar("s_CoversUpdateOperationInProgress", false)
MapVar("s_DbgDrawLOS", false)
MapVar("s_DbgDrawLOF", false)
MapVar("s_DbgDrawLOF_Objects", {})
MapVar("s_DbgDrawLOF_EYE", false)
MapVar("s_DbgDrawIgnoreSmoke", false)
MapVar("s_DbgDrawLastTarget", false)
MapVar("s_DbgDrawTargetDummies", false)
DefineClass.DebugCoverDraw = {
__parents = {"CObject"},
flags = {efSelectable = false, gofPermanent = false},
}
DefineClass.DebugCoverDrawNorthLow = {__parents = {"DebugCoverDraw"}, entity = "CoverNorth"}
DefineClass.DebugCoverDrawEastLow = {__parents = {"DebugCoverDraw"}, entity = "CoverEast"}
DefineClass.DebugCoverDrawSouthLow = {__parents = {"DebugCoverDraw"}, entity = "CoverSouth"}
DefineClass.DebugCoverDrawWestLow = {__parents = {"DebugCoverDraw"}, entity = "CoverWest"}
DefineClass.DebugCoverDrawNorthHigh = {__parents = {"DebugCoverDraw"}, entity = "CoverNorth_High"}
DefineClass.DebugCoverDrawEastHigh = {__parents = {"DebugCoverDraw"}, entity = "CoverEast_High"}
DefineClass.DebugCoverDrawSouthHigh = {__parents = {"DebugCoverDraw"}, entity = "CoverSouth_High"}
DefineClass.DebugCoverDrawWestHigh = {__parents = {"DebugCoverDraw"}, entity = "CoverWest_High"}
local function StopCoversUpdateThread()
DeleteThread(s_CoversUpdateThread)
s_CoversUpdateThread = false
s_CoversThreadBBox = false
end
local function HashPoint(pt)
return string.format("point(%d,%d,%d)", pt:x(), pt:y(), pt:z())
end
function AreCoversShown()
return not not g_dbgCoversShown
end
local debugcover_offset = const.SlabSizeX / 2 - 10 * guim / 100
local debugcovers = {
{ -- up
[const.CoverLow] = { cover = "DebugCoverDrawNorthLow", offset = point(0, -debugcover_offset, 0), angle = 90 * 60 },
[const.CoverHigh] = { cover = "DebugCoverDrawNorthHigh", offset = point(0, -debugcover_offset, 0), angle = 90 * 60 },
},
{ -- right
[const.CoverLow] = { cover = "DebugCoverDrawEastLow", offset = point(debugcover_offset, 0, 0), angle = 2 * 90 * 60 },
[const.CoverHigh] = { cover = "DebugCoverDrawEastHigh", offset = point(debugcover_offset, 0, 0), angle = 2 * 90 * 60 },
},
{ -- down
[const.CoverLow] = { cover = "DebugCoverDrawSouthLow", offset = point(0, debugcover_offset, 0), angle = 3 * 90 * 60 },
[const.CoverHigh] = { cover = "DebugCoverDrawSouthHigh", offset = point(0, debugcover_offset, 0), angle = 3 * 90 * 60 },
},
{ -- left
[const.CoverLow] = { cover = "DebugCoverDrawWestLow", offset = point(-debugcover_offset, 0, 0), angle = 0 },
[const.CoverHigh] = { cover = "DebugCoverDrawWestHigh", offset = point(-debugcover_offset, 0, 0), angle = 0 },
}
}
function DbgDrawCovers(dbg, bbox, dont_toggle, dont_rebuild)
local total = GetClock()
dbg = dbg or ""
local old = MapGet(s_CoversUpdateOperationInProgress and bbox or "map", "DebugCoverDraw")
for _, dbg in ipairs(old) do
DoneObject(dbg)
end
--DbgClearVectors()
if not dont_toggle then
g_dbgCoversShown = not g_dbgCoversShown
end
if not g_dbgCoversShown then
DbgDrawPassSlabs(false)
StopCoversUpdateThread()
if not IsEditorActive() then
StartWallInvisibilityThread()
HideFloorsAbove(999)
else
XEditorFiltersUpdateVisibility()
end
Msg("DbgCoversUpdated", bbox)
return
end
g_dbgCoversShown = dbg or g_dbgCoversShown
local dbg_draw_pass_objs = DbgDrawPassSlabs("on", "terrain pass", nil, bbox)
local rebuild = GetClock()
bbox = bbox or GetMapBox()
if not dont_rebuild then
bbox = RebuildCovers(bbox)
end
rebuild = GetClock() - rebuild
local floor = IsEditorActive() and XEditorFilters:GetFilter("HideFloor") or 0
if floor == 0 then floor = 999 end
BuildBuildingsData()
local ptExtend = point(const.SlabSizeX, const.SlabSizeY, const.SlabSizeZ * 2)
ForEachCover(bbox, -1, function(x, y, z, up, right, down, left)
z = z or terrain.GetHeight(x, y)
local pt = point(x, y, z)
local bbox_room = Extend(empty_box, pt):grow(ptExtend)
local room = EnumVolumes(bbox_room, "smallest")
local bld_meta = VolumeBuildingsMeta[room and room.building or false]
if bld_meta and bld_meta[floor] and z >= bld_meta[floor].box:minz() - 5 * guim / 10 then
return -- don't add debug covers that would be hidden because of the floor editor filter
end
for i, val in ipairs{ up, right, down, left } do
local t = debugcovers[i][val]
if t then
local cover = PlaceObject(t.cover)
cover:SetPos(pt + t.offset)
cover:SetAngle(t.angle)
end
end
end)
if string.match(dbg, "box") then
local pt1 = bbox:min()
local x, y, z = bbox:sizexyz()
local xx, yy, zz = point(x, 0, 0), point(0, y, 0), point(0, 0, z)
DbgAddPoly({
pt1, pt1 + xx, pt1 + xx + yy, pt1 + yy,pt1,
pt1 + zz, pt1 + zz + xx, pt1 + zz + xx + yy, pt1 + zz + yy, pt1 + zz})
DbgAddPoly({pt1 + xx, pt1 + xx + zz})
DbgAddPoly({pt1 + xx + yy, pt1 + xx + yy + zz})
DbgAddPoly({pt1 + yy, pt1 + yy + zz})
end
total = GetClock() - total
if not s_CoversUpdateOperationInProgress then
local count = MapCount(bbox, "DebugCoverDraw")
print(string.format("Covers: %d, DebugPassDraw objects: %d, Rebuild: %dms, Debug Info: %dms, Total: %dms", count, dbg_draw_pass_objs, rebuild, total - rebuild, total))
end
if not IsEditorActive() then
StartWallInvisibilityThread()
end
Msg("DbgCoversUpdated", bbox)
end
local function DbgCoverUpdate(op_finished, bbox, objects)
if not g_dbgCoversShown then return end
bbox = GetCoversVoxelPatchAlignedTaskBox(bbox)
s_CoversThreadBBox = s_CoversThreadBBox and AddRects(s_CoversThreadBBox, bbox) or bbox
if op_finished then
DbgDrawCovers(g_dbgCoversShown, s_CoversThreadBBox, "don't toggle")
if s_CoversUpdateOperationInProgress then
s_CoversUpdateOperationInProgress = false
StopCoversUpdateThread()
end
return
end
s_CoversUpdateOperationInProgress = true
DeleteThread(s_CoversUpdateThread)
s_CoversUpdateThread = CreateMapRealTimeThread(function()
Sleep(200)
local resume = ArePassEditsForEditOpSuspended()
if resume then
ResumePassEditsForEditOp()
end
for _, obj in ipairs(objects) do
obj:ApplySurfaces()
end
if resume then
SuspendPassEditsForEditOp()
end
terrain.RebuildPassability(s_CoversThreadBBox)
DbgDrawCovers(g_dbgCoversShown, s_CoversThreadBBox, "don't toggle")
s_CoversUpdateThread = false
s_CoversThreadBBox = false
end)
end
function OnMsg.EditorCategoryFilterChanged(c, filter)
if c == "HideFloor" and g_dbgCoversShown then
DbgDrawCovers(nil, nil, "dont_toggle")
end
end
function OnMsg.EditorHeightChanged(op_finished, bbox)
DbgCoverUpdate(op_finished, bbox)
end
function OnMsg.OnPassabilityChanged(bbox)
if not s_CoversUpdateOperationInProgress then
DelayedCall(0, DbgCoverUpdate, true, bbox)
end
end
local function CoversUpdate(op_finished, objects)
local bbox = GetObjectsBBox(objects):SetInvalidZ()
local ptExtend = point(const.SlabSizeX, const.SlabSizeY)
bbox = box(bbox:min() - ptExtend, bbox:max() + ptExtend)
DbgCoverUpdate(op_finished, bbox, objects)
end
function OnMsg.EditorObjectOperation(op_finished, objects)
CoversUpdate(op_finished, objects)
end
function OnMsg.EditorCallbackPreUndoRedo(objects)
CoversUpdate(false, objects)
end
function OnMsg.CombatObjectDied(obj, bbox)
DbgCoverUpdate(false, bbox)
end
local function DbgCoverRemoveInvalidWallSlabs(maps)
if not IsRealTimeThread() then
CreateRealTimeThread(DbgCoverRemoveInvalidWallSlabs, maps)
return
end
maps = maps or ListMaps()
if type(maps) == "string" and string.match(maps, "current") then
maps = {GetMapName()}
end
ForEachMap(maps, function()
local to_remove = setmetatable({}, weak_values_meta)
MapForEach("map", "WallSlab", function(obj)
if obj.class == "WallSlab" and not IsValidEntity(obj:GetEntity()) then
table.insert(to_remove, obj)
end
end)
for _, obj in ipairs(to_remove) do
DoneObject(obj)
end
print(string.format("Removed %d invalid WallSlab objects.", #to_remove))
SaveMap("no backup")
end)
end
DefineClass.DebugVisDummy =
{
__parents = { "AppearanceObject" },
flags = {
efSelectable = false, efWalkable = false, efCollision = false,
efApplyToGrids = false, efShadow = false, efSunShadow = false,
cfConstructible = false,
cofComponentColorizationMaterial = true,
cofComponentCollider = false,
},
attack_color_modifier = RGB(0, 200, 100),
target_color_modifier = RGB(0, 100, 200),
template_id = "Barry",
__toluacode = Object.__toluacode,
CloneFrom = function(self, obj)
local appearance = obj and obj.Appearance or ChooseUnitAppearance(self.template_id, self.handle)
self:ApplyAppearance(appearance)
if obj then
self.stance = obj.stance
self.current_weapon = obj.current_weapon
end
local weapon1, weapon2
if obj then
weapon1, weapon2 = obj:GetActiveWeapons()
else
weapon1 = Firearm
end
local wobj1 = IsKindOf(weapon1, "Firearm") and weapon1:CreateVisualObj(self)
local wobj2 = IsKindOf(weapon2, "Firearm") and weapon2:CreateVisualObj(self)
local attached_weapons = self:GetAttaches("WeaponVisual")
for i, o in ipairs(attached_weapons or empty_table) do
if o ~= wobj1 and o ~= wobj2 then
DoneObject(o)
end
end
if wobj1 then
self:Attach(wobj1, self:GetSpotBeginIndex("Weaponr"))
end
if wobj2 then
self:Attach(wobj2, self:GetSpotBeginIndex("Weaponl"))
end
self:SetState(obj:GetState(), 0, 0)
local phase = self:GetAnimMoment(self:GetStateText(), "hit") or 0
self:SetAnimPhase(1, phase)
self:SetAngle(obj:GetAngle())
self:SetPos(obj:GetPos())
end,
}
local function DbgPlaceAttackDummy(obj, pos, angle, anim, phase, target_pos)
local o = PlaceObject("DebugVisDummy")
o:CloneFrom(obj)
o:SetColorModifier(o.attack_color_modifier)
for i, attach in ipairs(o:GetAttaches()) do
attach:SetColorModifier(o.attack_color_modifier)
end
pos = pos or obj:GetPos()
angle = target_pos and CalcOrientation(pos, target_pos) or angle or obj:GetAngle()
anim = anim or obj:GetActionRandomAnim("Fire", obj.stance or "Standing")
phase = phase or obj:GetAnimMoment(anim, "hit") or 0
o:SetState(anim, 0, 0)
o:SetAnimPhase(1, phase)
o:SetAnimSpeed(1, 0)
o:SetAngle(angle)
o:SetPos(pos)
if target_pos then
local ikCmp = o:GetAnimComponentIndexFromLabel(1, "AimIK")
if ikCmp ~= 0 then
o:SetAnimComponentTarget(1, ikCmp, target_pos, InvalidPos(), 0, 0)
end
end
return o
end
local function DbgPlaceTargetDummy(obj, dummy)
local o = PlaceObject("DebugVisDummy")
o:CloneFrom(obj)
o:SetColorModifier(o.target_color_modifier)
for i, attach in ipairs(o:GetAttaches()) do
attach:SetColorModifier(o.target_color_modifier)
end
if not IsValid(dummy) and type(dummy) == "table" then
if dummy.anim then
o:SetStateText(dummy.anim, 0, 0)
local phase = o:GetAnimMoment(dummy.anim, "hit") or 0
o:SetAnimPhase(1, phase)
end
if dummy.phase then
o:SetAnimPhase(1, dummy.phase)
end
if dummy.angle then
o:SetAngle(dummy.angle)
end
if dummy.pos then
o:SetPos(dummy.pos)
end
end
o:SetAnimSpeed(1, 0)
return o
end
local function ClearTargetObjects()
local dummies = s_DbgDrawLOF_Objects
for k, obj in ipairs(dummies) do
if IsValid(obj) then
DoneObject(obj)
end
end
table.iclear(dummies)
end
local clrClearHit = RGB(0, 200, 100)
local clrObstructionHit = RGB(250, 100, 0)
local clrStuckToTarget = RGB(30, 30, 30)
local clrAttackPos = RGB(0, 50, 255)
local clrForcedTargetHit = RGB(0, 130, 150)
local clrCollisionTarget = RGB(0, 255, 100)
local clrCollisionPierce = RGB(255, 100, 0)
local clrCollisionIgnored = RGB(160, 160, 160)
local clrCollisionStuckPower = RGB(255, 255, 0)
local clrCollisionImpenetrable = RGB(255, 0, 0)
local clrLOSLines = {
const.clrWhite,
const.clrRed,
const.clrGreen,
const.clrCyan,
const.clrBlue,
const.clrPink,
const.clrYellow,
const.clrOrange,
const.clrMagenta,
}
local function AddLine(p1, p2, color)
local path = pstr("")
path:AppendVertex(p1, color)
path:AppendVertex(p2)
local line = PlaceObject("Polyline")
table.insert(s_DbgDrawLOF_Objects, line)
line:SetPos(p1)
line:SetMesh(path)
end
local function AddCollision(pos, clr, power)
local collision = PlaceObject("Mesh")
collision:SetMesh(CreateSphereVertices(3*guic, clr))
table.insert(s_DbgDrawLOF_Objects, collision)
collision:SetPos(pos)
if power then
local text = PlaceObject("Text")
table.insert(s_DbgDrawLOF_Objects, text)
text:SetText(string.format("%d", power))
text:SetPos(pos + point(0, 0, 5 * guim / 100))
text:SetTextStyle("BugReportScreenshot")
text:SetColor(clr)
end
end
local function DbgLOFGetTargets(unit)
local targets = MapGet("map", {"ExplosiveContainer", "Landmine"}) or {}
for i = #targets, 1, -1 do
if targets[i]:IsDead() then
table.remove(targets, i)
end
end
local enemies = GetEnemies(unit)
for _, enemy in ipairs(enemies) do
if not enemy:IsDead() then
table.insert(targets, enemy)
end
end
table.sortby_field(targets, "handle")
return targets
end
function DbgDrawLOF(targets, attacker, pos)
ClearTargetObjects()
if targets == false then
return
end
if attacker == nil and IsKindOf(SelectedObj, "Unit") then
attacker = SelectedObj
end
if not IsValid(attacker) then
return
end
if IsValid(targets) then
targets = { targets }
end
if not targets and IsKindOf(attacker, "Unit") then
targets = DbgLOFGetTargets(attacker)
end
if not targets or #targets == 0 then
return
end
local default_attack = attacker:GetDefaultAttackAction()
local weapons
if default_attack then
local weapon1, weapon2
weapon1, weapon2, weapons = default_attack:GetAttackWeapons(attacker)
weapons = weapons or { weapon1 }
end
local lof_params = {
obj = attacker,
step_pos = GetPassSlab(pos or attacker) or pos or attacker:GetPos(),
action_id = default_attack.id,
weapon = weapons[1],
stance = attacker.stance,
prediction = true,
output_collisions = true,
group_spots = false,
can_use_covers = true,
output_ignored_hits = true,
force_hit_seen_target = not config.DisableForcedHitSeenTarget,
ignore_smoke = s_DbgDrawIgnoreSmoke,
output_all_segments = true,
}
if IsKindOf(weapons[1], "FirearmBase") and weapons[1].emplacement_weapon then
lof_params.emplacement_weapon = true
end
local attack_dummies = GetAttackDummies(lof_params)
local all_targets_attack_data = {}
for attack_dummy_idx, dummy in ipairs(attack_dummies) do
lof_params.stance = dummy.stance
lof_params.los_stance = attacker.stance == "Crouch" and "Crouch" or dummy.stance
lof_params.step_pos = dummy.step_pos
lof_params.angle = dummy.angle
lof_params.cone_angle = dummy.cone_angle
lof_params.can_use_covers = false
for k, weapon in ipairs(weapons) do
lof_params.weapon = weapon
local targets_attack_data = GetLoFData(attacker, targets, lof_params)
all_targets_attack_data[attack_dummy_idx] = all_targets_attack_data[attack_dummy_idx] or targets_attack_data
for target_idx, target in ipairs(targets) do
local attack_data = targets_attack_data[target_idx]
if attack_data and attack_data.lof and not (attack_dummy_idx > 1 and attacker.stance == "Crouch" and all_targets_attack_data[1][target_idx].los == 0) then
if not attack_data.emplacement_weapon then
local target_pos = attack_data.target_pos
if not target_pos then
local idx = table.find(attack_data.lof, "target_spot", "Torso") or 1
target_pos = attack_data.lof[1] and attack_data.lof[1].lof_pos2
end
local o = DbgPlaceAttackDummy(attacker, attack_data.step_pos, attack_data.angle, attack_data.anim, attack_data.phase, target_pos)
table.insert(s_DbgDrawLOF_Objects, o)
end
for j, line_data in ipairs(attack_data.lof) do
if (line_data.eye_hit or false) == s_DbgDrawLOF_EYE then
local pos = line_data.lof_pos1
AddLine(pos, line_data.attack_pos, clrAttackPos)
pos = line_data.attack_pos
local target_pos = line_data.target_pos
local clrLine = clrClearHit
for k, collision_data in ipairs(line_data.hits) do
local hit_pos = collision_data.pos
AddLine(pos, hit_pos, clrLine)
if collision_data.ignored then
if not IsKindOf(collision_data.obj, "SmokeObj") then
clrLine = clrForcedTargetHit
end
else
clrLine = clrObstructionHit
end
local clrHit
if k == 1 and collision_data.obj == target then
clrHit = clrCollisionTarget
elseif collision_data.ignored and IsKindOf(collision_data.obj, "SmokeObj") then
clrHit = clrClearHit
elseif k < #line_data.hits then
clrHit = clrCollisionPierce
else
clrHit = clrCollisionStuckPower
end
AddCollision(hit_pos, clrHit)
pos = hit_pos
end
if IsCloser(line_data.lof_pos1, pos, target_pos) then
AddLine(pos, target_pos, clrStuckToTarget)
end
end
end
end
end
end
end
end
function DbgDrawLOS(targets, attacker)
ClearTargetObjects()
if targets == false then
return
end
if attacker == nil and IsKindOf(SelectedObj, "Unit") then
attacker = SelectedObj
end
if IsValid(targets) then
targets = { targets }
end
if targets == nil and attacker and IsKindOf(attacker, "Unit") then
targets = DbgLOFGetTargets(attacker)
end
if not attacker or not targets or #targets == 0 then
return
end
local attacker_pos = GetPassSlab(attacker) or attacker:GetPos()
local lof_params = {
obj = attacker,
step_pos = attacker_pos,
stance = attacker.stance,
can_use_covers = true,
}
local attack_dummies = GetAttackDummies(lof_params)
if attacker.stance == "Crouch" then
attack_dummies = { attack_dummies[1] }
end
for i, dummy in ipairs(attack_dummies) do
if dummy.step_pos ~= attacker_pos then
local dummy_obj = DbgPlaceAttackDummy(attacker, dummy.step_pos, dummy.angle, dummy.anim, dummy.phase, dummy.target_pos)
table.insert(s_DbgDrawLOF_Objects, dummy_obj)
end
end
local los = DebugLOS(targets, attacker, -1, attacker.stance)
for i, line_data in ipairs(los) do
local start_pos = line_data.pos1
local target_pos = line_data.pos2
local clr = line_data.los_level == 1 and const.clrGreen or const.clrBlue
if line_data.hits and #line_data.hits > 0 then
local hit_pos = line_data.hits[1].pos
AddLine(start_pos, hit_pos, clr)
AddLine(hit_pos, target_pos, clrStuckToTarget)
for k, collision_data in ipairs(line_data.hits) do
AddCollision(collision_data.pos, clrStuckToTarget)
end
else
AddLine(start_pos, target_pos, clr)
AddCollision(target_pos, clr)
end
end
end
local function DbgUpdateLOFLines(unit)
if unit == nil then
unit = SelectedObj
end
if s_DbgDrawLOF then
if unit and unit == SelectedObj then
DbgDrawLOF(nil, unit)
elseif not SelectedObj then
DbgDrawLOF(false)
end
end
if s_DbgDrawLOS then
if unit and unit == SelectedObj then
DbgDrawLOS(nil, unit)
elseif not SelectedObj then
DbgDrawLOS(false)
end
end
end
OnMsg.UnitMovementDone = DbgUpdateLOFLines
OnMsg.UnitStanceChanged = DbgUpdateLOFLines
OnMsg.SelectionChange = DbgUpdateLOFLines
function DbgDrawToggleLOS()
PauseInfiniteLoopDetection("DebugLOSVis")
if s_DbgDrawLOS then
s_DbgDrawLOS = false
DbgDrawLOS(false)
else
if s_DbgDrawLOF then
DbgDrawToggleLOF()
end
s_DbgDrawLOS = true
DbgDrawLOS()
end
ResumeInfiniteLoopDetection("DebugLOSVis")
end
function DbgDrawToggleLOF()
PauseInfiniteLoopDetection("DebugLOFVis")
if s_DbgDrawLOF then
s_DbgDrawLOF = false
DbgDrawLOF(false)
else
if s_DbgDrawLOS then
DbgDrawToggleLOS()
end
s_DbgDrawLOF = true
DbgDrawLOF()
end
ResumeInfiniteLoopDetection("DebugLOFVis")
end
function DbgDrawLOFNext()
if s_DbgDrawLOS then
DbgDrawToggleLOS()
end
s_DbgDrawLOF = true
local targets = DbgLOFGetTargets(SelectedObj)
s_DbgDrawLastTarget = targets[(table.find(targets, s_DbgDrawLastTarget) or 0) + 1] or targets[1] or false
DbgDrawLOF(s_DbgDrawLastTarget, SelectedObj)
end
-- will update the visible covers according to the editor's floor filter
local function UpdateCoverDebug()
if g_dbgCoversShown then
DbgDrawCovers(nil, nil, "dont_toggle")
end
end
OnMsg.GameEnterEditor = UpdateCoverDebug
OnMsg.GameExitEditor = UpdateCoverDebug
local target_dummy_color_modifier = RGB(30, 0, 100)
local function ShowTargetDummy(obj)
if not obj then return end
obj:SetColorModifier(target_dummy_color_modifier)
for i, attach in ipairs(obj:GetAttaches()) do
attach:SetColorModifier(target_dummy_color_modifier)
end
obj:SetVisible(true)
--obj:SetOpacity(80)
end
function DbgDrawShowTargetDummies(show)
s_DbgDrawTargetDummies = show or false
if show then
MapForEach("map", "TargetDummy", ShowTargetDummy)
else
MapForEach("map", "TargetDummy", Object.SetVisible, false)
end
end
function DbgDrawToggleTargetDummies()
DbgDrawShowTargetDummies(not s_DbgDrawTargetDummies)
end
OnMsg.NewTargetDummy = Object.SetVisible
function OnMsg.NewTargetDummy(obj)
if s_DbgDrawTargetDummies then
ShowTargetDummy(obj)
end
end
function DumpStepVectors()
local entities = { "EquipmentBarry_Top", "EquipmentLivewire_Top", "Animal_Hyena", "Animal_Crocodile", "Animal_Hen" }
local filename = string.format("TmpData/AnimStepData.log")
local f = io.open(filename, "w+")
local log = {}
for i, entity in ipairs(entities) do
local states = GetStates(entity)
for j, anim in ipairs(states) do
local step_len = GetStepLength(entity, anim)
if step_len ~= 0 then
local duration = GetAnimDuration(entity, anim)
local compensate = GetAnimCompensate(entity, anim)
local txt = string.format('Entity "%s", Anim: "%s", Duration: %d, %s, Step Lenght: %d\n', entity, anim, duration, compensate, step_len)
table.insert(log, txt)
local last_step = point30
for phase = 1, duration do
local step = GetEntityStepVector(entity, anim, 0, phase)
if step ~= last_step then
last_step = step
table.insert(log, string.format("%10d : %5d, %d, %d\n", phase, step:xyz()))
end
end
table.insert(log, "\n")
f:write(log)
table.iclear(log)
end
end
end
f:close()
end