Nestharus
o-o
- Reaction score
- 83
Extremely useful for tower defense and tower war maps. Need I say more?
Instructions for Use
Be sure to make 1 tile for each of your checkpoints unbuildable (common for wintermaul war maps, the rects). Doing this will ensure that players won't be able to blanket a checkpoint with towers.
Players Will Be Able To Blanket An Entire Area Of The Map If They Are Allowed To Build on All Corners of that Area
Anti Block System
Simply copy and paste this into a map and players will no longer be able to block. Keep in mind that this small snippet requires the Costs lib in order to retrieve unit total gold/wood costs for refund.
Instructions for Use
Be sure to make 1 tile for each of your checkpoints unbuildable (common for wintermaul war maps, the rects). Doing this will ensure that players won't be able to blanket a checkpoint with towers.
Players Will Be Able To Blanket An Entire Area Of The Map If They Are Allowed To Build on All Corners of that Area
JASS:
library IPB /* v3.0.2.6
*************************************************************************************
*
* Determines if the path between two points, the target point having a radius, is blocked.
*
************************************************************************************
*
* */uses/*
*
* */ IsPathable /* hiveworkshop.com/forums/submissions-414/snippet-ispathable-199131/
* */ Tile /* hiveworkshop.com/forums/submissions-414/snippet-tile-211368/
* */ RegisterPlayerUnitEvent /* hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/
* */ UnitIndexer /* hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
* */ GetUnitCollision /* hiveworkshop.com/forums/submissions-414/snippet-needs-work-getunitcollision-180495/
*
************************************************************************************
*
* SETTINGS
*
* This is how much work is done per thread when loading pathing map.
* Tweak this value in debug mode until the pathing map crash message goes away to minimize load time.
*/
globals
private constant integer BUFFER = 6300
endglobals
/*
*
************************************************************************************
*
* function IsPathBlocked takes unit obstruction returns boolean
* - Determines whether or not there is a path after a new obstruction is placed
* - obstruction refers to the new obstruction
*
************************************************************************************/
private keyword P
private function NormalizeAngle takes real angle returns real
local integer a
if (0 > angle) then
set a = R2I(angle*180/bj_PI - 45)/90*90
else
set a = R2I(angle*180/bj_PI + 45)/90*90
endif
if (0 > a or 360 < a) then
set a = a - a/360*360
if (0 > a) then
set a = a + 360
endif
endif
return a/180.*bj_PI
endfunction
private function CalculateAngleBetweenPoints takes real x, real y, real x2, real y2 returns real
return Atan2(y2 - y, x2 - x)
endfunction
private function CalculateComponentX takes real angle returns real
return 64*Cos(angle)
endfunction
private function CalculateComponentY takes real angle returns real
return 64*Sin(angle)
endfunction
globals
private integer tS
private P array pS
private hashtable ib
private hashtable ih = null
endglobals
private struct IsHit extends array
method operator [] takes integer y returns boolean
return LoadBoolean(ih, this, y)
endmethod
method operator []= takes integer y, boolean v returns nothing
call SaveBoolean(ih, this, y, v)
endmethod
static method clear takes nothing returns nothing
call FlushParentHashtable(ih)
set ih = InitHashtable()
endmethod
endstruct
private struct IsBlocked extends array
method operator [] takes integer y returns boolean
return LoadBoolean(ib, this, y)
endmethod
method operator []= takes integer y, boolean v returns nothing
call SaveBoolean(ib, this, y, v)
endmethod
endstruct
private struct P extends array
private static integer ic = 0
private static integer array r
readonly static integer tx = 0
readonly static integer ty = 0
readonly static boolean ib = true
readonly integer x
readonly integer y
readonly boolean og0
readonly boolean og90
readonly boolean og180
readonly boolean og270
readonly integer ax
readonly integer ay
private static constant integer R = 8
static method create takes integer x, integer y, integer ax, integer ay returns thistype
local thistype t
set t = r[0]
if (0 == t) then
set t = ic + 1
set ic = t
else
set r[0] = r[t]
endif
set t.x = x
set t.y = y
set IsHit[x][y] = true
set ib = x + R < tx or x - R > tx or y + R < ty or y - R > ty
set t.ax = ax
set t.ay = ay
if (0 == ax) then
set t.og0 = not IsBlocked[x+64][y]
set t.og180 = not IsBlocked[x-64][y]
else
set t.og90 = not IsBlocked[x][y+64]
set t.og270 = not IsBlocked[x][y-64]
endif
return t
endmethod
static method clear takes nothing returns nothing
set ic = 0
set r[0] = 0
endmethod
static method initialize takes integer targetX, integer targetY returns nothing
set thistype.tx = targetX
set thistype.ty = targetY
set thistype.ib = true
endmethod
static method ipc takes nothing returns boolean
static if DEBUG_MODE then
local integer p = 645
else
local integer p = 1725
endif
local thistype t = pS[tS]
local boolean o0
local boolean o1
local integer x = t.x + t.ax
local integer y = t.y + t.ay
set UnitIndexer.enabled = false
loop
exitwhen 0 == t or 0 == p or not ib
set p = p - 1
set x = t.x + t.ax
set y = t.y + t.ay
if (IsHit[x][y]) then
set tS = tS - 1
set r[t] = r[0]
set r[0] = t
set t = pS[tS]
elseif (not IsBlocked[x][y]) then
set IsHit[x][y] = true
set ib = x + R < tx or x - R > tx or y + R < ty or y - R > ty
set t.x = x
set t.y = y
if (0 == t.ax) then //vertical
set o0 = t.og0
set o1 = t.og180
set t.og0 = not IsBlocked[x+64][y]
set t.og180 = not IsBlocked[x-64][y]
if (o0 != t.og0 and not o0 and not IsHit[x+64][y]) then
if (o1 != t.og180 and not o1 and not IsHit[x-64][y]) then
set pS[tS+1] = P.create(x, y, -64, 0)
set tS = tS + 2
set t = P.create(x, y, 64, 0)
set pS[tS] = t
else
set tS = tS + 1
set t = P.create(x, y, 64, 0)
set pS[tS] = t
endif
elseif (o1 != t.og180 and not o1 and not IsHit[x-64][y]) then
set tS = tS + 1
set t = P.create(x, y, -64, 0)
set pS[tS] = t
endif
else //horizantal
set o0 = t.og90
set o1 = t.og270
set t.og90 = not IsBlocked[x][y+64]
set t.og270 = not IsBlocked[x][y-64]
if (o0 != t.og90 and not o0 and not IsHit[x][y+64]) then
if (o1 != t.og270 and not o1 and not IsHit[x][y-64]) then
set pS[tS+1] = P.create(x, y - 64, 0, -64)
set t = P.create(x, y, 0, 64)
set pS[tS] = t
else
set tS = tS + 1
set t = P.create(x, y, 0, 64)
set pS[tS] = t
endif
elseif (o1 != t.og270 and not o1 and not IsHit[x][y-64]) then
set tS = tS + 1
set t = P.create(x, y, 0, -64)
set pS[tS] = t
endif
endif
else
set tS = tS - 1
set x = t.x
set y = t.y
if (0 == t.ax) then
if (not IsBlocked[x+64][y] and not IsHit[x+64][y]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, 64, 0)
endif
if (not IsBlocked[x-64][y] and not IsHit[x-64][y]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, -64, 0)
endif
else
if (not IsBlocked[x][y+64] and not IsHit[x][y+64]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, 0, 64)
endif
if (not IsBlocked[x][y-64] and not IsHit[x][y-64]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, 0, -64)
endif
endif
set r[t] = r[0]
set r[0] = t
set t = pS[tS]
endif
endloop
set UnitIndexer.enabled = true
return true
return not ib or 0 == t
endmethod
endstruct
private function ClearAll takes nothing returns nothing
call P.clear()
set tS = 0
call IsHit.clear()
endfunction
private struct IBS extends array
private static trigger isPathBlockedT
private static method initialize takes integer x, integer y, integer tx, integer ty returns boolean
local real angle
local real m
local integer ax
local integer ay
local boolean init = false
call ClearAll()
call P.initialize(tx, ty)
set angle = NormalizeAngle(CalculateAngleBetweenPoints(x, y, tx, ty))
set m = NormalizeAngle(angle + bj_PI)
set ax = NormalizeXY(CalculateComponentX(m))
set ay = NormalizeXY(CalculateComponentY(m))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
set m = NormalizeAngle(angle + bj_PI/2)
set ax = NormalizeXY(CalculateComponentX(m))
set ay = NormalizeXY(CalculateComponentY(m))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
set m = NormalizeAngle(angle + bj_PI+bj_PI/2)
set ax = NormalizeXY(CalculateComponentX(m))
set ay = NormalizeXY(CalculateComponentY(m))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
set ax = NormalizeXY(CalculateComponentX(angle))
set ay = NormalizeXY(CalculateComponentY(angle))
if (not IsBlocked[x+ax][y+ay]) then
set tS = tS + 1
set pS[tS] = P.create(x, y, ax, ay)
set init = true
endif
return init
endmethod
static method calculate takes integer ox, integer oy, integer tx, integer ty returns boolean
if (initialize(ox, oy, tx, ty)) then
loop
exitwhen TriggerEvaluate(isPathBlockedT)
endloop
endif
return P.ib
endmethod
private static method onInit takes nothing returns nothing
set isPathBlockedT = CreateTrigger()
call TriggerAddCondition(isPathBlockedT, Condition(function P.ipc))
endmethod
endstruct
private struct RL extends array
private static integer x
private static integer y
private static boolean array h
private static method upd takes unit u, boolean ip returns nothing
local integer x
local integer y
local integer s
local integer cx
local integer cy
local integer mx
local integer my
if (h[GetUnitUserData(u)] != ip) then
set h[GetUnitUserData(u)] = ip
set x = NormalizeXY(GetUnitX(u))
set y = NormalizeXY(GetUnitY(u))
set s = NormalizeXY(GetUnitCollision(u))-32
set mx = x - s
set my = y - s
set x = x + s
set y = y + s
set cx = x
set cy = y
if (0 < s) then
loop
loop
set IsBlocked[cx][cy] = ip
exitwhen cy == my
set cy = cy - 64
endloop
exitwhen cx == mx
set cx = cx - 64
set cy = y
endloop
endif
endif
endmethod
private static method updateD takes nothing returns boolean
if (null == GetIndexedUnit()) then
if (IsUnitType(GetTriggerUnit(), UNIT_TYPE_STRUCTURE)) then
call upd(GetTriggerUnit(), false)
endif
else
if (IsUnitType(GetIndexedUnit(), UNIT_TYPE_STRUCTURE)) then
call upd(GetIndexedUnit(), false)
endif
endif
return false
endmethod
private static method updateI takes nothing returns boolean
if (IsUnitType(GetIndexedUnit(), UNIT_TYPE_STRUCTURE)) then
call upd(GetIndexedUnit(), true)
endif
return false
endmethod
private static unit pc
debug private static boolean crashed
private static method lm takes nothing returns boolean
static if DEBUG_MODE then
local integer p = 300
else
local integer p = BUFFER
endif
local integer x = RL.x
local integer y = RL.y
local integer max = WorldBounds.maxX-32
local integer mx = WorldBounds.minX-32
local integer my = WorldBounds.minY+32
local integer pt = PATH_TYPE_WALKABILITY
local integer m = (WorldBounds.maxX-WorldBounds.minX)/64
local hashtable h = ib
local unit u
if (0 > m) then
set m = -m
endif
set m = m - 1
debug set crashed = true
loop
loop
call SetUnitPosition(pc, x, y)
call SaveBoolean(h, x, y, GetUnitX(pc) != x or GetUnitY(pc) != y)
set x = x - 64
exitwhen x == mx
endloop
set x = max
set p = p - m
set y = y - 64
exitwhen y == my or 1 > p
endloop
debug set crashed = false
set h = null
set RL.x = x
set RL.y = y
return y == my
endmethod
private static method onInit takes nothing returns nothing
local trigger ct = CreateTrigger()
local group g = CreateGroup()
local unit u
set ib = InitHashtable()
call GroupEnumUnitsInRect(g, WorldBounds.world, null)
loop
set u = FirstOfGroup(g)
exitwhen null == u
call GroupRemoveUnit(g,u)
if (IsUnitType(u, UNIT_TYPE_STRUCTURE)) then
set h[GetUnitUserData(u)] = true
endif
endloop
call DestroyGroup(g)
set g = null
call TriggerAddCondition(ct, Condition(function thistype.lm))
set thistype.x = WorldBounds.maxX-32
set thistype.y = WorldBounds.maxY-32
set UnitIndexer.enabled = false
set pc = GetPathingUnit(PATH_TYPE_WALKABILITY)
loop
exitwhen TriggerEvaluate(ct)
debug if (crashed) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,10,"PATHING MAP CRASH")
debug return
debug endif
endloop
set pc = null
call SetUnitX(pc,WorldBounds.minX)
call SetUnitY(pc,WorldBounds.minY)
set UnitIndexer.enabled = true
call TriggerClearConditions(ct)
call DestroyTrigger(ct)
set ct = null
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.updateD)
call RegisterUnitIndexEvent(Condition(function thistype.updateI), UnitIndexer.INDEX)
call RegisterUnitIndexEvent(Condition(function thistype.updateD), UnitIndexer.DEINDEX)
endmethod
endstruct
private struct PC extends array
private static boolean tb
private static boolean bb
private static boolean lb
private static boolean rb
private static boolean trb
private static boolean tlb
private static boolean blb
private static boolean brb
readonly static integer tbx
readonly static integer tby
readonly static integer bbx
readonly static integer bby
readonly static integer lbx
readonly static integer lby
readonly static integer rbx
readonly static integer rby
private static method initBlocks takes integer x, integer y, integer r returns nothing
local integer s = r - 32
local integer so = s + 64
local integer mx
local integer my
local integer cx
local integer cy
local integer off = 32
if (0 == s) then
set off = 0
endif
//top
set cx = x + s
set mx = x - s
set cy = y + so
loop
if (IsBlocked[cx][cy]) then
set tb = true
else
set tb = false
set tbx = cx
set tby = cy
endif
exitwhen cx == mx or not tb
set cx = cx - 64
endloop
//left
set cy = y + s
set my = y - s
set cx = x - so
loop
if (IsBlocked[cx][cy]) then
set lb = true
else
set lb = false
set lbx = cx
set lby = cy
endif
exitwhen cy == my or not lb
set cy = cy - 64
endloop
//bottom
set cx = x + s
set mx = x - s
set cy = y - so
loop
if (IsBlocked[cx][cy]) then
set bb = true
else
set bb = false
set bbx = cx
set bby = cy
endif
exitwhen cx == mx or not bb
set cx = cx - 64
endloop
//right
set cy = y + s
set my = y - s
set cx = x + so
loop
if (IsBlocked[cx][cy]) then
set rb = true
else
set rb = false
set rbx = cx
set rby = cy
endif
exitwhen cy == my or not rb
set cy = cy - 64
endloop
//top left
set tlb = false
if (not lb) then
set cy = y + s
set my = y + off
set cx = x - so
loop
set tlb = tlb or IsBlocked[cx][cy]
exitwhen cy == my or tlb
set cy = cy - 64
endloop
endif
if (not tb) then
set cx = x - off
set mx = x - s
set cy = y + so
loop
set tlb = tlb or IsBlocked[cx][cy]
exitwhen cx == mx or tlb
set cx = cx - 64
endloop
endif
set tlb = tlb or IsBlocked[x-so][y+so]
//top right
set trb = false
if (not rb) then
set cy = y + s
set my = y + off
set cx = x + so
loop
set trb = trb or IsBlocked[cx][cy]
exitwhen cy == my or trb
set cy = cy - 64
endloop
endif
if (not tb) then
set cx = x + s
set mx = x + off
set cy = y + so
loop
set trb = trb or IsBlocked[cx][cy]
exitwhen cx == mx or trb
set cx = cx - 64
endloop
endif
set trb = trb or IsBlocked[x+so][y+so]
//bottom right
set brb = false
if (not rb) then
set cy = y - off
set my = y - s
set cx = x + so
loop
set brb = brb or IsBlocked[cx][cy]
exitwhen cy == my or brb
set cy = cy - 64
endloop
endif
if (not bb) then
set cx = x + s
set mx = x + off
set cy = y - so
loop
set brb = brb or IsBlocked[cx][cy]
exitwhen cx == mx or brb
set cx = cx - 64
endloop
endif
set brb = brb or IsBlocked[x+so][y-so]
//bottom left
set blb = false
if (not lb) then
set cy = y - off
set my = y - s
set cx = x - so
loop
set blb = blb or IsBlocked[cx][cy]
exitwhen cy == my or blb
set cy = cy - 64
endloop
endif
if (not bb) then
set cx = x - off
set mx = x - s
set cy = y - so
loop
set blb = blb or IsBlocked[cx][cy]
exitwhen cx == mx or blb
set cx = cx - 64
endloop
endif
set blb = blb or IsBlocked[x-so][y-so]
endmethod
static method init takes integer x, integer y, integer r returns boolean
local boolean p
call initBlocks(x, y, r)
if (not tb and not (bb and rb and lb)) then
set p = (trb or (brb and not bb) or rb) and (tlb or lb or (blb and not bb))
if (p) then
if (((rb and bb) or (lb and bb)) and ((trb != blb) or (tlb != brb))) then
set p = not bb or (not (rb and lb) and tlb and trb)
endif
endif
if (p) then
if (not bb) then //bottom to top
return IBS.calculate(PC.bbx, PC.bby, PC.tbx, PC.tby)
elseif (not rb and trb) then //right to top
return IBS.calculate(PC.rbx, PC.rby, PC.tbx, PC.tby)
elseif (tlb) then //left to top
return IBS.calculate(PC.lbx, PC.lby, PC.tbx, PC.tby)
endif
endif
endif
if (not bb and not (rb and tb and lb)) then
set p = ((trb and not tb) or brb or rb) and ((tlb and not tb) or lb or blb)
if (p) then
if (((rb and tb) or (lb and tb)) and ((trb != blb) or (tlb != brb))) then
set p = not tb or (not (rb and lb) and blb and brb)
endif
endif
if (p) then
if (not rb and brb) then //right to bottom
return IBS.calculate(PC.rbx, PC.rby, PC.bbx, PC.bby)
elseif (not tb) then //top to bottom
return IBS.calculate(PC.tbx, PC.tby, PC.bbx, PC.bby)
elseif (blb) then //left to bototm
return IBS.calculate(PC.lbx, PC.lby, PC.bbx, PC.bby)
endif
endif
endif
if (not lb and not (bb and rb and tb)) then
set p = (tlb or tb or (trb and not rb)) and (blb or bb or (brb and not rb))
if (p) then
if (((tb and rb) or (rb and bb)) and ((trb != blb) or (tlb != brb))) then
set p = not rb or (not (tb and bb) and tlb and blb)
endif
endif
if (p) then
if (not bb and blb) then //bottom to left
return IBS.calculate(PC.bbx, PC.bby, PC.lbx, PC.lby)
elseif (not tb and tlb) then //top to left
return IBS.calculate(PC.tbx, PC.tby, PC.lbx, PC.lby)
else //right to left
return IBS.calculate(PC.rbx, PC.rby, PC.lbx, PC.lby)
endif
endif
endif
if (not rb and not (tb and lb and bb)) then
set p = ((tlb and not lb) or tb or trb) and ((blb and not lb) or bb or brb)
if (p) then
if (((lb and bb) or (lb and tb)) and ((trb != blb) or (tlb != brb))) then
set p = not lb or (not (tb and bb) and trb and brb)
endif
endif
if (p) then
if (not tb and trb) then //top to right
return IBS.calculate(PC.tbx, PC.tby, PC.rbx, PC.rby)
elseif (not lb) then //left to right
return IBS.calculate(PC.lbx, PC.lby, PC.rbx, PC.rby)
elseif (brb) then //bottom to right
return IBS.calculate(PC.bbx, PC.bby, PC.rbx, PC.rby)
endif
endif
endif
return false
endmethod
endstruct
function IsPathBlocked takes unit u returns boolean
return PC.init(NormalizeXY(GetUnitX(u)), NormalizeXY(GetUnitY(u)), NormalizeXY(GetUnitCollision(u)))
endfunction
endlibrary
Anti Block System
Simply copy and paste this into a map and players will no longer be able to block. Keep in mind that this small snippet requires the Costs lib in order to retrieve unit total gold/wood costs for refund.
JASS:
struct AntiBlock extends array
private static method checkBlock takes nothing returns boolean
local texttag tag
if (IsPathBlocked(GetTriggerUnit())) then
set tag = CreateTextTag()
call SetTextTagText(tag, "Attempted to Block With "+GetUnitName(GetTriggerUnit()), 10 * 0.023 / 10)
call SetTextTagPos(tag, GetUnitX(GetTriggerUnit()), GetUnitY(GetTriggerUnit()), 128)
call SetTextTagLifespan(tag, 2)
call SetTextTagPermanent(tag, false)
call SetTextTagVelocity(tag, 0, .1)
call SetTextTagFadepoint(tag, 1.5)
call SetTextTagVisibility(tag, GetLocalPlayer() == GetTriggerPlayer())
set tag = null
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD, GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD) + GetUnitTotalGoldCost(GetTriggerUnit()))
call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER, GetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER) + GetUnitTotalWoodCost(GetTriggerUnit()))
call RemoveUnit(GetTriggerUnit())
endif
return false
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_CONSTRUCT_START, function thistype.checkBlock)
endmethod
endstruct
Attachments
-
42.7 KB Views: 404