• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] Z Slash, Caster moves faster??

Status
Not open for further replies.
Level 5
Joined
Aug 16, 2010
Messages
97
Hello everyone.
By the request of a mod, I changed my spell's script so it uses one timer for the whole spell. hence less performance issue. But since I used that method, a new problem has popped up. The caster, with every cast, moves faster and faster, while he should maintain the same speed. I have read thorugh this but haven't found a clue as to what causes this weird problem. Would be glad if you could tell me.
Thanks in advance.

[JASS="Spell Code"] library ZSlash requires UnitIndexer, TimerUtils, SpellEffectEvent, IsTerrainWalkable

//====================================================================================================================================
//
// By Dr.Killer
//
//====================================================================================================================================


//====================================================================================================================================
// Introduction: The hero launches himself forward, slashing enemies along his path and wounding them. Then he proceeds to slash
// more enemies in a Z pattern.
//====================================================================================================================================


//====================================================================================================================================
// Requirements:
//
// - CTL
// http://www.hiveworkshop.com/forums/jass-resources-412/snippet-constant-timer-loop-32-a-201381/
//
// - TimerUtils (Vexorian's version)
// http://www.wc3c.net/showthread.php?t=101322
//
// - UnitIndexer
// http://www.hiveworkshop.com/forums/jass-resources-412/system-unit-indexer-172090/
//
// - SpellEffectEvent
// http://www.hiveworkshop.com/forums/...pelleffectevent-187193/?highlight=spelleffect
//
// - IsPathable
// http://http://www.hiveworkshop.com/forums/jass-resources-412/snippet-pathable-199131/
//
// The following libraries are required by the above systems:
//
// - RegisterPlayerUnitEvent
// http://hiveworkshop.com/forums/showthread.php?t=203338
//
// - Event
// http://hiveworkshop.com/forums/submissions-414/snippet-event-186555/
//
// - WorldBounds
// http://hiveworkshop.com/forums/jass-functions-413/snippet-worldbounds-180494/
//====================================================================================================================================


//====================================================================================================================================
// Credits
//
// - Vexorian for TimerUtils, JassHelper and contributions to WC3 modding in general
// - Nestharus for UnitIndexer, Event, WorldBounds, CTL
// - Magtheridon96 for his awesome MeatMash spell from which I learned a lot (and copied a bit) and RegisterPlayerUnitEvent
// - Bribe for SpellEffectEvent
//
//====================================================================================================================================


//====================================================================================================================================
// Important Notice
//
// Feel free to edit, modify, revise or anything that comes to your mind, just remember to credit me as the original creator
// wherever you use this.
//====================================================================================================================================


//=============================================================
// Configuration
//=============================================================
globals
//Editor stuff
private constant integer ABIL_CODE = 'A001'

//Spell stuff
private constant boolean LIMIT_TARGETS = false //Should the maximum number of slashed enemies be limited?
private constant boolean LIMIT_INJURY = true //Should a victim be abale to be damaged more than once?
private constant boolean INV = true //Should the caster turn invulnerable during the spell?
private constant boolean PAN = true //Should I pan the camera to hero's location in the end?
private constant real JUMP_DIST = 450. //How far the hero launches himself forward (Affects the size of Z)
private constant real Z_ANGLE = (bj_PI) / 4. //The angle between Z's horizontal and diagonal line. Best looking at Pi/4.

private constant real DUR = .9 //How long it takes the hero to reach the end of each line in Z
private constant real INTERVAL = 0.03 //Interval between hero's movements. A lower amount results in a smooth
//movement but is more demanding.

private constant real D_JUMP_DIST = JUMP_DIST/Sin(Z_ANGLE)
private constant real TRAVEL_1 = JUMP_DIST / (DUR/INTERVAL)
private constant real TRAVEL_2 = D_JUMP_DIST / (DUR/INTERVAL)
private constant real PATH_OFFSET = 64. //Used when the hero gets stuck somewhere in the end of the spell.
//That's how much the hero's moved to find a walkable ground

private constant real RADIUS = 105.

private constant integer RED = 255
private constant integer GREEN = 255
private constant integer BLUE = 255
private constant integer ALPHA = 130

private constant attacktype ATTACK_TYPE = ATTACK_TYPE_HERO
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_NORMAL
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS

private constant string EFFECT_PATH = "Abilities\\Weapons\\PhoenixMissile\\Phoenix_Missile_mini.mdl"
private constant string BLOOD_EFFECT_PATH = "Objects\\Spawnmodels\\Human\\HumanBlood\\HumanBloodFootman.mdl"
private constant string ATTACH_POINT = "chest"

endglobals

//How much damage is dealt upon a slash
private function DamageOnSlash takes integer lvl returns real
return I2R(lvl*100)
endfunction

//Here you can decide what units will be affected by this spell
private function TargetFilter takes unit target, unit caster returns boolean
return IsUnitEnemy(target, GetOwningPlayer(caster)) and not (IsUnitType(target, UNIT_TYPE_DEAD) or IsUnitType(target, UNIT_TYPE_MECHANICAL) or IsUnitType(target, UNIT_TYPE_FLYING))
endfunction

//=============================================================
// End of Configuration
//=============================================================


//=============================================================
// Spell Code
//=============================================================
private struct Z extends array

private static integer array rn
private static integer ic = 0

private static unit array hero
private static real array totalTravel
private static integer array travelStage
private static real array angle
private static effect array sfx
private static real array dx
private static real array dy

//These coordinates are used to prevente our hero form getting stuck in the trees, etc.




private static group tempGroup //Used for unit enumeration


private static method onPeriod takes nothing returns nothing
local timer t = GetExpiredTimer()
local thistype this = 1
local real x
local real y
local real hero_X
local real hero_Y
local unit tempUnit


//Iterate over all spell instances
loop
exitwhen integer(this)>ic
set hero_X = GetUnitX(hero[this])
set hero_Y = GetUnitY(hero[this])

if hero[this] != null then

if travelStage[this] == 1 then //We're running along the first line
//call BJDebugMsg("ic: "+I2S(ic))

if totalTravel[this] < JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]

call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)

set totalTravel[this] = totalTravel[this] + (JUMP_DIST / (DUR/INTERVAL))

call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null

if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
call BJDebugMsg("i: "+I2S(this))
else
set totalTravel[this] = 0.
set travelStage[this] = travelStage[this] + 1
set angle[this] = angle[this] + bj_PI + Z_ANGLE
set dx[this] = D_JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = D_JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//call BJDebugMsg("first ende")
endif

elseif travelStage[this] == 2 then

if totalTravel[this] < D_JUMP_DIST then
set x = hero_X + dx[this]
set y = hero_Y + dy[this]

call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)

set totalTravel[this] = totalTravel[this] + (D_JUMP_DIST / (DUR/INTERVAL))

call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null

if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
//call BJDebugMsg("this: "+I2S(this))
else
set totalTravel[this] = 0.
set travelStage[this] = travelStage[this] + 1
set angle[this] = angle[this] - bj_PI - Z_ANGLE
set dx[this] = JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])
//call BJDebugMsg("second ende")
endif

else

//Third travel stage
if totalTravel[this] < JUMP_DIST then

set x = hero_X + dx[this]
set y = hero_Y + dy[this]

call SetUnitX(hero[this], x)
call SetUnitY(hero[this], y)

set totalTravel[this] = totalTravel[this] + (JUMP_DIST / (DUR/INTERVAL))

call GroupEnumUnitsInRange(tempGroup, x, y, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set tempUnit = FirstOfGroup(tempGroup)
exitwhen tempUnit == null

if TargetFilter(tempUnit, hero[this]) then
call UnitDamageTarget(hero[this], tempUnit, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, tempUnit, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, tempUnit)
endloop
//call BJDebugMsg("this: "+I2S(this))
else

//call BJDebugMsg("third ende")
//Spell has ended
call SetUnitInvulnerable(hero[this], false)
if GetLocalPlayer() == GetOwningPlayer(hero[this]) then
call SelectUnit(hero[this], true)
if PAN then
call PanCameraTo(hero_X, hero_Y)
endif
endif
call DestroyEffect(sfx[this])
call SetUnitVertexColor(hero[this], 255, 255, 255, 255)

//Cleanup
set hero[this] = null
set sfx[this] = null
set dx[this] = 0.
set dy[this] = 0.

//Deallocate this instance
set rn[this] = rn[0]
set rn[0] = this

endif
endif

endif
set this = this+1
endloop

//Cleanup Section
set tempUnit = null
set t = null
endmethod






private static method onCast takes nothing returns nothing
local unit u = GetTriggerUnit()
local thistype this = rn[0]
local real tx = GetSpellTargetX()
local real ty = GetSpellTargetY()
local real cx //These are used for geometric calculations and determining the path of hero
local real cy //They actually help draw my Z
local integer lvl = GetUnitAbilityLevel(u, ABIL_CODE)


if this == 0 then
set ic = ic + 1
set this = ic
else
set rn[0] = rn[this]
endif

set hero[this] = u
set cx = GetUnitX(u)
set cy = GetUnitY(u)
set angle[this] = Atan2(ty-cy, tx-cx)
set totalTravel[this] = 0.
set travelStage[this] = 1
set u = null

set dx[this] = JUMP_DIST / (DUR/INTERVAL)*Cos(angle[this])
set dy[this] = JUMP_DIST / (DUR/INTERVAL)*Sin(angle[this])

//Apply invunerability
if INV then
call SetUnitInvulnerable(hero[this], true)
endif

//Make hero transparent
call SetUnitVertexColor(hero[this], RED, GREEN, BLUE, ALPHA)

//Apply eyecandy
set sfx[this] = AddSpecialEffectTarget(EFFECT_PATH, hero[this], ATTACH_POINT)

//De-select the hero
if GetLocalPlayer() == GetOwningPlayer(hero[this]) then
call SelectUnit(hero[this], false)
endif

//First damage nearby enemies
call GroupEnumUnitsInRange(tempGroup, cx, cy, RADIUS, null)
call GroupRemoveUnit(tempGroup, hero[this])
loop
set u = FirstOfGroup(tempGroup)
exitwhen u==null

if TargetFilter(u, hero[this]) then
call UnitDamageTarget(hero[this], u, DamageOnSlash(GetUnitAbilityLevel(hero[this], ABIL_CODE)), false, false, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call DestroyEffect(AddSpecialEffectTarget(BLOOD_EFFECT_PATH, u, ATTACH_POINT))
endif
call GroupRemoveUnit(tempGroup, u)
endloop

//Now we start the Stage 1 timer that moves our hero every INTEVAL seconds along the top most line of Z
if integer(this) == 1 then
call TimerStart(NewTimer(), INTERVAL, true, function thistype.onPeriod)
endif

//Cleanup
set u = null

endmethod

private static method onInit takes nothing returns nothing
set tempGroup = CreateGroup()
call RegisterSpellEffectEvent(ABIL_CODE, function thistype.onCast)
endmethod

endstruct

endlibrary
[/code]
 

Attachments

  • Z Slash.w3x
    44.9 KB · Views: 52
Level 7
Joined
Jan 22, 2013
Messages
293
Ok, without even looking at your code, I can clearly cut down on what you need to look at.

These are your possible problems you can Do to fix it.

1. To end up with something that progressively makes you faster means each time you might "Set a speed" it is not reseting it back to default after the end of the use or before you use the spell. meaning it will progressively move faster each time because it is stacking from math previously given to it that is still existing from its last use.

Well I was going to give you a number too but that's all I got.

FYI, I have no Clue how to read your code, I just know how to fix things lol.
 
Status
Not open for further replies.
Top