Example report

Lanternfall Defense: 2 (F) to 75 (C) on a copy

A hero defense we built from our own MIT-licensed template to show what a report looks like. The problems in its script are deliberate, and they are ones real maps have. Every number below is the engine's own output.

Verdict

Would not load on 3.0.1. Fixed on a copy.

The script declares IsItemEquipped, a name Warcraft III 3.0.0 gave to a new native, so the game rejects the map. It also leaks a location and a unit group every second and throws away two special effects. Three operations fixed 15 of 23 findings; the rest are listed under "What this did not fix".

23→8findings
3→0Errors
159.5 MB→11.2 MBleaked by minute 240 (static estimate)

The plan that ran

The engine suggested four operations. The experimental one (optimize.scatter) was left out, as a one-click plan would.

  1. Apply the map doctor's targeted fixes fix.doctor risk: review
    • blz-301-rename: 0 site(s), 1 refused
    • native-clash-rename: 2 site(s)
    • hp-fraction-threshold: 1 site(s)
    • local-location-remove: 3 site(s), 1 refused
  2. Stop handle leaks in code that runs all game leak.hot risk: safe
    • OnPickup (line 45): local unit u set to null before 1 exit(s)
    • SpawnBoss (line 90): local trigger t set to null before 1 exit(s)
    • SpawnWave (line 105): local unit u set to null before 1 exit(s)
    • HealAura (line 132): local group g freed with DestroyGroup before 1 exit(s)
    • HealAura (line 133): local unit v set to null before 1 exit(s)
    • OnCreepDeath (line 147): local unit u set to null before 1 exit(s)
    • OnGoalEntered (line 157): local unit u set to null before 1 exit(s)
  3. Destroy fire-and-forget effects optimize.effects risk: review
    • ShowLantern: 1 effect(s) wrapped in DestroyEffect (line 38)
    • SpawnWave: 1 effect(s) wrapped in DestroyEffect (line 100)

Runs on

Each build the map was checked against, before and after. "Not tested" means the rule pack has no verdict for that build, not that it passed.

1.26
Before FailsAfter Fails

w3i format v31 needs patch 1.32 or newer

1.31
Before FailsAfter Fails

w3i format v31 needs patch 1.32 or newer

1.32
BeforeNot testedAfterNot tested
2.0
BeforeNot testedAfterNot tested
3.0.0
Before FailsAfterNot tested
3.0.1
Before FailsAfter Runs

Area grades

The score is the lowest weighted area. How each grade is computed is on the scoring page.

Stability
2 F→80 B
Performance
46 F→69 C
Security
100 A→100 A
Cleanliness
100 A→100 A
Text
100 A→100 A

Findings, before the fix

  • Errors3 found · 3 fixed
  • Errors
    The map declares a function with the same name as a native added in 3.0.0, so it fails to compile or load.
    FixedBRK-native-name-clash · line 34 in IsItemEquippedfix.doctor
  • Errors
    A function, global or local in the map has the name of a native in the target build's prelude.
    FixedBRK-prelude-name-clash · line 34 in IsItemEquipped
  • Errors
    pjass rejects the script against this build's common.j and Blizzard.j, so the map does not compile.
    FixedGATE-pjass · line 34
  • Severe7 found · 4 fixed
  • Severe
    Leaks in repeating code
    Still there, now line 90PERF-L01 · line 126leak.hot
  • Severe
    A location is stored and never removed, so every call leaks one.
    Still therePERF-L01 · line 102 in SpawnWavefix.doctor
  • Severe
    A location is stored and never removed, so every call leaks one.
    FixedPERF-L01 · line 127 in HealAurafix.doctor
  • Severe
    A group made by a BJ function is neither destroyed nor flagged with bj_wantDestroyGroup, so it leaks.
    FixedPERF-L02 · line 128 in HealAura
  • Severe
    A special effect is created and its handle thrown away, so it can never be destroyed.
    FixedPERF-L04 · line 118 in SpawnWave
  • Severe
    A special effect is created and its handle thrown away, so it can never be destroyed.
    FixedPERF-L04 · line 40 in ShowLantern
  • Severe
    A handle is created or game state changes inside a GetLocalPlayer branch, which desyncs the other players.
    Still thereDESYNC-localplayer-handle · line 40 in ShowLantern
  • Warnings4 found · 3 fixed
  • Warnings
    Unit orders re-issued many times a second
    Still there, now line 100PERF-U01 · line 98optimize.scatter
  • Warnings
    Leaks in per-event code
    FixedPERF-L04 · line 38optimize.effects
  • Warnings
    A life threshold below 1 is compared with absolute hit points, so a "25 percent" phase only fires at death.
    FixedLOGIC-hp-fraction-threshold · line 94 in SpawnBossfix.doctor
  • Warnings
    The call uses an unprefixed 3.0.0 native whose removal is announced, so the map stops compiling once it goes.
    FixedBRK-unprefixed-300-call · line 46 in OnPickupfix.doctor
  • Info9 found · 5 fixed
  • Info
    A handle local is not set to null before the function returns.
    FixedPERF-L05 · line 90 in SpawnBoss
  • Info
    A handle local is not set to null before the function returns.
    Still therePERF-L05 · line 102 in SpawnWave
  • Info
    A handle local is not set to null before the function returns.
    FixedPERF-L05 · line 127 in HealAura
  • Info
    A periodic callback creates units or effects inside a loop with no visible per-tick cap.
    Still therePERF-M02 · line 110 in SpawnWave
  • Info
    A handle local is not set to null before the function returns.
    FixedPERF-L05 · line 45 in OnPickup
  • Info
    A handle local is not set to null before the function returns.
    FixedPERF-L05 · line 141 in OnCreepDeath
  • Info
    A handle local is not set to null before the function returns.
    FixedPERF-L05 · line 151 in OnGoalEntered
  • Info
    A handle local is not set to null before the function returns.
    Still therePERF-L05 · line 55 in SpawnHeroes
  • Info
    A handle local is not set to null before the function returns.
    Still therePERF-L05 · line 166 in InitCustomTriggers

What changed

Every line the fix touched in war3map.j (+19 / −5 lines). Nothing else in the archive was modified.

@@ -32,5 +32,5 @@ // Old inventory helper, written before 3.0.0 added a native with the same name.function IsItemEquipped takes unit u, integer itemId returns booleanfunction MD_IsItemEquipped takes unit u, integer itemId returns boolean    return GetInventoryIndexOfItemTypeBJ(u, itemId) > 0endfunction@@ -38,5 +38,5 @@function ShowLantern takes player p, real x, real y returns nothing    if GetLocalPlayer() == p then        call AddSpecialEffect("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", x, y)        call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\TalkToMe\\TalkToMe.mdl", x, y))    endifendfunction@@ -44,8 +44,9 @@function OnPickup takes nothing returns nothing    local unit u = GetTriggerUnit()    if IsItemEquipped(u, 'ratf') then    if MD_IsItemEquipped(u, 'ratf') then        call Say(GetUnitName(u) + " carries the Claws of Attack.")        call ShowLantern(GetOwningPlayer(u), GetUnitX(u), GetUnitY(u))    endif    set u = nullendfunction @@ -92,6 +93,7 @@    call GroupAddUnit(creeps, boss)    call IssuePointOrder(boss, "attack", GOAL_X, GOAL_Y)    call TriggerRegisterUnitStateEvent(t, boss, UNIT_STATE_LIFE, LESS_THAN, 0.25)    call TriggerRegisterUnitStateEvent(t, boss, UNIT_STATE_LIFE, LESS_THAN, GetUnitState(boss, UNIT_STATE_MAX_LIFE) * 0.25)    call TriggerAddAction(t, function OnBossEnraged)    set t = nullendfunction @@ -116,5 +118,5 @@        set k = k + 1    endloop    call AddSpecialEffectLoc("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl", spawn)    call DestroyEffect(AddSpecialEffectLoc("Abilities\\Spells\\Human\\MassTeleport\\MassTeleportCaster.mdl", spawn))    call Say("Wave " + I2S(wave) + " of " + I2S(WAVES))    if wave >= WAVES then@@ -122,4 +124,9 @@        call DestroyTimer(GetExpiredTimer())    endif    call RemoveLocation(spawn)    set spawn = null    call RemoveLocation(goal)    set u = null    set goal = nullendfunction @@ -136,4 +143,9 @@        endif    endloop    call RemoveLocation(c)    call DestroyGroup(g)    set g = null    set v = null    set c = nullendfunction @@ -146,4 +158,5 @@        endif    endif    set u = nullendfunction @@ -161,4 +174,5 @@        endif    endif    set u = nullendfunction 

Proof ladder

What was checked on the fixed copy. A hollow seal means the check was not run for this example, so we do not claim it.

  1. L0 Your original is untouchedThe input file's SHA-256 is identical before and after the run.
  2. L1 The copy opens and nothing was lostRe-opened from scratch; only war3map.j changed.
  3. L2 The script still compilespjass on the output. Errors before and after: 3.0.1 0->0, 1.26.0 0->0
  4. L3 The re-scan finds nothing newThe fixed copy was scanned again; no finding appeared that was not there before.
  5. L4 Opens in the World EditorNot run for this example (needs the editor harness on a lab PC).
  6. L5 Plays in a real gameNot run in our lab for this example.

What this did not fix

  • Severe A location is stored and never removed, so every call leaks one.
    The leak engine refused this site: the location is assigned inside a loop, where a mechanical fix could free a point that is still in use.
  • Severe A handle is created or game state changes inside a GetLocalPlayer branch, which desyncs the other players.
    Needs a person: the effect must be created for every player and only its model path chosen per player. The desync guide shows the pattern.
  • Warnings Unit orders re-issued many times a second
    optimize.scatter could address it, but it is rated experimental, so it was left out of the plan.
  • Warnings Leaks in repeating code
    This aggregate finding now points at line 90: the boss trigger is created each time the boss spawns, which happens once per game here, so it was left alone.
  • Info A handle local is not set to null before the function returns.
    Locals set once at start-up, or a location the engine would not touch inside a loop. Harmless in this map.
  • Info A periodic callback creates units or effects inside a loop with no visible per-tick cap.
    A wave loop that creates units without a per-tick cap. That is the design of a wave map.
  • Errors Does not run on 1.26 or 1.31
    The map is saved in the w3i format v31, which needs patch 1.32 or newer. We do not down-convert maps.

Map facts

Map
Lanternfall Defense (example, ours)
Players
4
Tileset
Lordaeron Summer
Script
JASS, 243 lines, 19 functions
Size
18,100 bytes before, 18,237 after
SHA-256
93955fd07b649749… → d72f1773e80e8725…
Terrain
From the MIT-licensed wc3-ts-template

Want this for your map?

Send it with a request: post it on our Discord with a link to the map's page. The community votes on Discord, and the top request is saved every week.