Download Lua/Dev/CoverDebug.lua from sirnii/myspace: direct link, hf CLI and curl.
- Browser
- Download file 22.1 kB
-
https://huggingface.co/spaces/sirnii/myspace/resolve/main/Lua/Dev/CoverDebug.lua
- Command line
-
hf download hf://spaces/sirnii/myspace/Lua/Dev/CoverDebug.lua
-
curl -L -o CoverDebug.lua https://huggingface.co/spaces/sirnii/myspace/resolve/main/Lua/Dev/CoverDebug.lua
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 | |