Cheddar
This is the way it was meant to be.
- Reaction score
- 126
I always liked the idea of a "Non-Triggered Hero" contest.
I always liked the idea of a "Non-Triggered Hero" contest.
That could be neat. I like that idea. :thup:I always liked the idea of a "Non-Triggered Hero" contest.
library HailTower requires AIDS, Damage, T32, xefx, TimerUtils, ImageUtils
globals
//===========================================================================================
/*
Hail Tower, by kingking (v1.1)
Description :
A tower that shoots hail to units. The damaged units are hurted by coldness.
Every attack makes the unit colder and colder, causing more damage.
Requires :
- AIDS
- Damage
- T32
- xefx
- TimerUtils
- ImageUtils
Implementation Steps :
- Implement required systems.
- Copy this trigger.
- Copy the .blps in this demo map to your map. The path must be same as well.
- Tweak settings / constants.
- Enjoy!
* Requires Jasshelper to compile this script.
Changelog :
v1.0 ~ First Release
v1.1 ~ Updated TextSplat module, making it supports up to infinite text instead of +99
*/
//===========================================================================================
//==================Tower Settings====================\\
private constant integer TOWER_ID = 039;h000039;
// -> The ID of tower.
private constant string UNIT_EFFECT = "Abilities\\Spells\\Other\\Drain\\ManaDrainTarget.mdl"
// -> Freezing effect.
private constant boolean ENABLE_EYE_CANDY = true
// -> Enable/Disable the art on tower. Disabling will improve the performance with loss of eye candy.
private constant string TOWER_EFFECT = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
// -> Art of eye candy.
private constant real ART_Z = 200.
// -> Height of eye candy.
private constant real ART_XY_EXTEND = 150.
// -> Theta for X/Y of eye candy.
private constant real ART_Z_EXTEND = 100.
// -> Theta for height of eye candy.
private constant real ART_SCALE = 1.
// -> Scaling for eye candy.
//=====================================================\\
//=================Effect Settings=====================\\
private constant real EFFECT_DURATION = 10.0
// -> Duration of freezing effect
private constant integer MAX_STACK = -1
// -> Maximum stack. (Set to -1 for infinite stacking)
//=====================================================\\
//==================Text Settings==================\\
private constant boolean ENABLE_TEXT = true
// -> Enable/Disable the text. Disabling it may improve the performance.
private constant integer TEXT_RED = 150
private constant integer TEXT_GREEN = 150
private constant integer TEXT_BLUE = 255
private constant real TEXT_DURATION = 3.0
private constant real TEXT_Z = 300.
//===================================================\\
endglobals
//==================Constant function(s)=================\\
private function Damage takes integer stackLevel returns real
return 30. * stackLevel
endfunction
//=======================================================\\
//==============================Text Splat, credit to PitzerMike============================\\
private struct Text extends imagex
private thistype prev
private thistype next
method asHead takes nothing returns nothing
set this.prev = this
set this.next = this
endmethod
method addText takes thistype text returns nothing
set this.next.prev = text
set text.next = this.next
set this.next = text
set text.prev = this
endmethod
method chainApplyAlpha takes integer alpha returns nothing
local thistype ori = this
set this = this.next
loop
exitwhen this == ori
set this.alpha = alpha
set this = this.next
endloop
endmethod
method chainApplyZ takes real z returns nothing
local thistype ori = this
set this = this.next
loop
exitwhen this == ori
set this.z = z
set this = this.next
endloop
endmethod
method chainDestroy takes nothing returns nothing
local thistype ori = this
set this = this.next
loop
exitwhen this == ori
set this.prev.next = this.next
set this.next.prev = this.prev
call this.destroy()
set this = this.next
endloop
call this.destroy()
endmethod
endstruct
private struct TextSplat
private static string array imagePath
private static integer tickAll
private static integer alphaDecrement
private static real zIncrement
private Text textList
private integer tick
private real z
private integer alpha
private method periodic takes nothing returns nothing
if .tick > T32_Tick then
set .z = .z + thistype.zIncrement
set .alpha = .alpha - thistype.alphaDecrement
call .textList.chainApplyZ(.z)
call .textList.chainApplyAlpha(.alpha)
else
call .textList.chainDestroy()
call .stopPeriodic()
call this.destroy()
endif
endmethod
implement T32x
static method new takes real x, real y, integer text returns nothing
local thistype this = thistype.allocate()
local string s = I2S(text)
local Text word
local integer length = StringLength(s)
local integer iterator = 0
set .alpha = 255
set .z = 300.
set .tick = thistype.tickAll + T32_Tick
set x = x - I2R((length / 2)) * 30.
set .textList = Text.create("ReplaceableTextures\\CommandButtons\\BTNSlowOn.blp",0.,0.,0.,0.,0.,false)
call .textList.asHead()
set word = Text.create("HailTower\\+.blp",64.,64.,x,y,0.,true)
set word.red = TEXT_RED
set word.green = TEXT_GREEN
set word.blue = TEXT_BLUE
set word.z = .z
call .textList.addText(word)
loop
exitwhen SubString(s,iterator,iterator+1) == ""
set x = x + 30.
set word = Text.create(imagePath[S2I(SubString(s,iterator,iterator+1))],64.,64.,x,y,0.,true)
set word.red = TEXT_RED
set word.green = TEXT_GREEN
set word.blue = TEXT_BLUE
set word.z = .z
call .textList.addText(word)
set iterator = iterator + 1
endloop
call .startPeriodic()
set s = null
endmethod
private static method onInit takes nothing returns nothing
set imagePath[0] = "HailTower\\0.blp"
set imagePath[1] = "HailTower\\1.blp"
set imagePath[2] = "HailTower\\2.blp"
set imagePath[3] = "HailTower\\3.blp"
set imagePath[4] = "HailTower\\4.blp"
set imagePath[5] = "HailTower\\5.blp"
set imagePath[6] = "HailTower\\6.blp"
set imagePath[7] = "HailTower\\7.blp"
set imagePath[8] = "HailTower\\8.blp"
set imagePath[9] = "HailTower\\9.blp"
set tickAll = R2I(TEXT_DURATION / T32_PERIOD)
set alphaDecrement = 255 / tickAll
set zIncrement = TEXT_Z / I2R(T32_FPS)
endmethod
endstruct
//==========================================================================================\\
//======================================= Stack =============================================\\
private struct StackData extends array
readonly integer stackLevel
private effect eff
private timer t
private method AIDS_onCreate takes nothing returns nothing
set .stackLevel = 0
endmethod
private method AIDS_onDestroy takes nothing returns nothing
if .stackLevel > 0 then
call DestroyEffect(.eff)
call ReleaseTimer(.t)
endif
endmethod
private static method removeEffect takes nothing returns nothing
local thistype this = GetTimerData(GetExpiredTimer())
set .stackLevel = 0
call DestroyEffect(.eff)
call ReleaseTimer(.t)
endmethod
method stackIncrement takes nothing returns nothing
set .stackLevel = .stackLevel + 1
if .stackLevel == 1 then
set .eff = AddSpecialEffectTarget(UNIT_EFFECT,.unit,"origin")
set .t = NewTimer()
call SetTimerData(.t,this)
else
call PauseTimer(.t)
if MAX_STACK > 0 and .stackLevel > MAX_STACK then
set .stackLevel = MAX_STACK
endif
endif
call TimerStart(.t,EFFECT_DURATION,false,function thistype.removeEffect)
endmethod
//! runtextmacro AIDS()
endstruct
//===========================================================================================================\\
//======================================Damage Detector==================================================\\
private struct Initializer extends array
private static method onDamage takes nothing returns boolean
local unit tower = null
local unit target = null
if GetUnitTypeId(GetEventDamageSource()) == TOWER_ID and Damage_IsAttack() then
set tower = GetEventDamageSource()
set target = GetTriggerUnit()
call Damage_BlockAll()
call StackData[target].stackIncrement()
call UnitDamageTargetEx(tower,target,Damage(StackData[target].stackLevel),false,false,ATTACK_TYPE_CHAOS,DAMAGE_TYPE_UNIVERSAL,null)
static if ENABLE_TEXT then
call TextSplat.new(GetUnitX(tower),GetUnitY(tower),StackData[target].stackLevel)
endif
endif
return false
endmethod
private static method onInit takes nothing returns nothing
local trigger trig = CreateTrigger()
call Damage_RegisterEvent(trig)
call TriggerAddCondition(trig,Condition(function thistype.onDamage))
endmethod
endstruct
//=======================================================================================================\\
//=================================Eye Candy==================================\\
private struct Projectile extends xefx
//Darn, I had to do this to handle xefx dummies. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite3" alt=":(" title="Frown :(" loading="lazy" data-shortname=":(" />
private real ox
private real oy
private real angle
private integer style
// 1 = Change in X-axis
// 2 = Change in Y-axis
private integer angsty
private method periodic takes nothing returns nothing
if this.angsty == 1 then
set this.angle = this.angle + 0.05
elseif this.angsty == 2 then
set this.angle = this.angle - 0.05
endif
if this.style == 1 then
set this.x = this.ox + ART_XY_EXTEND * Sin(this.angle)
elseif this.style == 2 then
set this.y = this.oy + ART_XY_EXTEND * Sin(this.angle)
endif
set this.z = ART_Z + ART_Z_EXTEND * Cos(this.angle)
endmethod
implement T32x
private method onDestroy takes nothing returns nothing
call .stopPeriodic()
endmethod
static method start takes real x, real y, integer sty, integer angsty returns thistype
local thistype this = thistype.create(x,y,0.)
set this.ox = x
set this.oy = y
set this.style = sty
set this.angle = GetRandomReal(0.,6.284)
set this.fxpath = TOWER_EFFECT
set this.z = ART_Z
set this.scale = ART_SCALE
set this.angsty = angsty
call .startPeriodic()
return this
endmethod
endstruct
private struct TowerData extends array
private real towerx
private real towery
private Projectile x1dummy
private Projectile y1dummy
private Projectile x2dummy
private Projectile y2dummy
private static method AIDS_filter takes unit u returns boolean
static if ENABLE_EYE_CANDY then
return GetUnitTypeId(u) == TOWER_ID
else
return false
endif
endmethod
private method AIDS_onCreate takes nothing returns nothing
set .towerx = GetUnitX(.unit)
set .towery = GetUnitY(.unit)
set .x1dummy = Projectile.start(.towerx,.towery,1,1)
set .y1dummy = Projectile.start(.towerx,.towery,2,1)
set .x2dummy = Projectile.start(.towerx,.towery,1,2)
set .y2dummy = Projectile.start(.towerx,.towery,2,2)
call SetUnitInvulnerable(.unit,true)
endmethod
private method AIDS_onDestroy takes nothing returns nothing
call .x1dummy.destroy()
call .y1dummy.destroy()
call .x2dummy.destroy()
call .y2dummy.destroy()
endmethod
//! runtextmacro AIDS()
endstruct
//============================================================================\\
endlibrary
Where's the map? I'm keen to look at a vJass tower
I made my submission in 2 days. Only takes a few hours.
EDIT: You have done A LOT to your map skyblader. As user-friendly as possible. I was considering adding comments to state what to change and what not.
Also I like the tower.
Thanks I was thinking there wasn't much eye candy... But I guess that's because I didn't want to make my tower use abilities. I like the eye candies of your tower though :thup:
Since it was my first attempt at a contest at all, I thought I'd do my best and see how I fared anyway
I just thought of an idea. If I remember how to code, I'll enter.