Zwiebelchen
You can change this now in User CP.
- Reaction score
- 60
A system that allows 2 coordinate layers instead of just the default one.
Basicly, the system grants you the possibility to create walkable bridges that also allow to walk beneath them.
It could also be used to create two-floor houses for FPS/TPS styled games.
The system provides the following functions:
The function simply returns the floor-layer the unit is currently at.
0 is the standard terrain layer, 1 is the bridge layer.
Allows to switch between terrain and bridge layer.
This is optional, in case you want to switch layers by using an elevator instead of "ordinary" stairs, where the system does the switching automaticly.
In order to get this system to work, you require the following registry functions:
Defines the areas the multi-floors are in.
Registers the unit types to the system that should be able to pass the bridge-layer.
Every registered unit types needs:
- an equivalent flying unit type
- two chaos-based morph abilities, to switch between ground and flying type
Comments & Discussion
The system is not very efficient.
True. However, I wrote this only for testing purposes. Maybe someone has a use for this.
How does it work?
All you need to do, is to use the register functions and place the "Walk Indicator" destructable like you would with an invisible platform. After that add air-pathing blockers to your area and you are done.
My unit doesn't step up the stairs automaticly!
Then maybe the z-offset for the first stair was to high. Either increase the offset setting in the system's constants, or lower the first "Walk Indicator" placed at your stairs.
The unit controls suck and the selection circle is still on the ground ...
Indeed. This is something the flawed engine of warcraft III messes up.
However, this system may still be very useful for those people that use 3rd person styled camera systems and arrow key controls. For this, its perfect.
Units on the ground layer behave weird when they try to pass air-pathing blockers
Yes ... this seems to be another bug in the wc3 engine. Air-pathing blockers suck.
Basicly, the system grants you the possibility to create walkable bridges that also allow to walk beneath them.
It could also be used to create two-floor houses for FPS/TPS styled games.
The system provides the following functions:
The function simply returns the floor-layer the unit is currently at.
0 is the standard terrain layer, 1 is the bridge layer.
Allows to switch between terrain and bridge layer.
This is optional, in case you want to switch layers by using an elevator instead of "ordinary" stairs, where the system does the switching automaticly.
In order to get this system to work, you require the following registry functions:
Defines the areas the multi-floors are in.
JASS:
Registers the unit types to the system that should be able to pass the bridge-layer.
Every registered unit types needs:
- an equivalent flying unit type
- two chaos-based morph abilities, to switch between ground and flying type
Comments & Discussion
The system is not very efficient.
True. However, I wrote this only for testing purposes. Maybe someone has a use for this.
How does it work?
All you need to do, is to use the register functions and place the "Walk Indicator" destructable like you would with an invisible platform. After that add air-pathing blockers to your area and you are done.
My unit doesn't step up the stairs automaticly!
Then maybe the z-offset for the first stair was to high. Either increase the offset setting in the system's constants, or lower the first "Walk Indicator" placed at your stairs.
The unit controls suck and the selection circle is still on the ground ...
Indeed. This is something the flawed engine of warcraft III messes up.
However, this system may still be very useful for those people that use 3rd person styled camera systems and arrow key controls. For this, its perfect.
Units on the ground layer behave weird when they try to pass air-pathing blockers
Yes ... this seems to be another bug in the wc3 engine. Air-pathing blockers suck.
JASS:
library MFS initializer Init
globals
private constant integer WalkIndicatorId = 039;B001039;
private constant integer FloorChangeMaxOffset = 40
private constant real HeightChangeVelocity = 1200
private constant integer DummyId = 039;h000039;
private constant player DummyOwner = Player(PLAYER_NEUTRAL_PASSIVE)
private constant real Update = 0.05
private unit dummy = null
private rect array Rects
private integer RectCount = 0
private constant group enum = CreateGroup()
private constant hashtable FloorHash = InitHashtable()
endglobals
public function GetFloor takes unit u returns integer
if u != null then
return LoadInteger(FloorHash, GetHandleId(u), 0)
endif
return 0
endfunction
public function SetFloor takes unit u, integer level returns nothing
if u != null then
call SaveInteger(FloorHash, GetHandleId(u), 0, level)
endif
endfunction
public function RegisterFloorArea takes real minx, real miny, real maxx, real maxy returns nothing
set Rects[RectCount] = Rect(minx, miny, maxx, maxy)
set RectCount = RectCount+1
endfunction
public function RegisterUnitMorphs takes integer unitground, integer unitfly, integer ground2fly, integer fly2ground returns nothing
call SaveInteger(FloorHash, unitground, 0, ground2fly)
call SaveInteger(FloorHash, unitfly, 0, fly2ground)
endfunction
private function GetZ takes real x, real y returns integer
local location l = null
local real z = 0
call SetUnitX(dummy, x)
call SetUnitY(dummy, y)
set l = GetUnitLoc(dummy)
set z = GetLocationZ(l)
call RemoveLocation(l)
set l = null
return R2I(z)
endfunction
private function RegisterWalkIndicator takes destructable d returns nothing
local integer x = R2I(GetDestructableX(d))
local integer y = R2I(GetDestructableY(d))
local integer tempx = x-32
local integer tempy = y-32
local integer z = GetZ(tempx, tempy)
if LoadInteger(FloorHash, tempx, tempy) < z then
call SaveInteger(FloorHash, tempx, tempy, z)
endif
set tempy = y+32
set z = GetZ(tempx, tempy)
if LoadInteger(FloorHash, tempx, tempy) < z then
call SaveInteger(FloorHash, tempx, tempy, z)
endif
set tempx = x+32
set z = GetZ(tempx, tempy)
if LoadInteger(FloorHash, tempx, tempy) < z then
call SaveInteger(FloorHash, tempx, tempy, z)
endif
set tempy = y-32
set z = GetZ(tempx, tempy)
if LoadInteger(FloorHash, tempx, tempy) < z then
call SaveInteger(FloorHash, tempx, tempy, z)
endif
call RemoveDestructable(d)
endfunction
private function ModInt takes integer dividend, integer divisor returns integer
return dividend - (dividend / divisor) * divisor
endfunction
private function XToGridX takes real x returns integer
if x < 0 then
return R2I(x) - ModInt(R2I(x), 64) - 32
else
return R2I(x) - ModInt(R2I(x), 64) + 32
endif
endfunction
private function UpdateZ takes nothing returns boolean
local unit u = GetFilterUnit()
local integer z = LoadInteger(FloorHash, XToGridX(GetUnitX(u)), XToGridX(GetUnitY(u)))
if HaveSavedInteger(FloorHash, GetUnitTypeId(u), 0) then //only perform update for registered unit-types
if GetFloor(u) > 0 then
if z == 0 then
call SetFloor(u, 0)
call UnitAddAbility(u, LoadInteger(FloorHash, GetUnitTypeId(u), 0))
endif
if R2I(GetUnitFlyHeight(u)) != z then
call SetUnitFlyHeight(u, z, HeightChangeVelocity)
endif
else
if z > 0 and z < FloorChangeMaxOffset then
call SetFloor(u, 1)
call UnitAddAbility(u, LoadInteger(FloorHash, GetUnitTypeId(u), 0))
if R2I(GetUnitFlyHeight(u)) != z then
call SetUnitFlyHeight(u, z, HeightChangeVelocity)
endif
endif
endif
endif
set u = null
return false
endfunction
private function UpdateAllRects takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= RectCount
call GroupEnumUnitsInRect(enum, Rects<i>, Condition(function UpdateZ))
set i = i + 1
endloop
endfunction
private function RegisterAllWalkIndicators takes nothing returns nothing
local destructable d = GetEnumDestructable()
if GetDestructableTypeId(d) == WalkIndicatorId then
call RegisterWalkIndicator(d)
endif
set d = null
endfunction
private function Init takes nothing returns nothing
local timer t = CreateTimer()
call TimerStart(t, Update, true, function UpdateAllRects)
set t = null
set dummy = CreateUnit(DummyOwner, DummyId, 0, 0, 0)
call SetUnitPathing(dummy, false)
call EnumDestructablesInRect(bj_mapInitialPlayableArea, null, function RegisterAllWalkIndicators)
endfunction
endlibrary</i>