Hatebreeder
So many apples
- Reaction score
- 381
Hey there,
I have been playing around with Unit Indexing lately, speaking of PUI (Perfect Unit Indexing) and came up with this little Spell.
As usual, i don't care about credits, but don't claim this as your own.
Any comments?
I have been playing around with Unit Indexing lately, speaking of PUI (Perfect Unit Indexing) and came up with this little Spell.
Describtion:
Requirements:
- New Gen Editor
- TT (Timer Ticker)
-PUI (Perfect Unit Indexing)
-SimError (Vex's Error Snipplet )
(all these (excluding New Gen) can be found in the demo map)
Screenshots:
Code:
Whenever one casts a Spell, one extracts the very essence of the Spell and creates an "Arcane Component". Each component can be fused together to form a deadly substance, though, there is a chance of 50% that it "reduces", reducing the total damage of the substance, but also has a 50% chance of "oxidizing", increasing the total damage of the substance sufficiently.
- New Gen Editor
- TT (Timer Ticker)
-PUI (Perfect Unit Indexing)
-SimError (Vex's Error Snipplet )
(all these (excluding New Gen) can be found in the demo map)
Screenshots:
JASS:
scope ArcaneAlchemy initializer Init
//******************************************************************
//* Arcane Alchemy *
//* by Hatebreeder *
//******************************************************************
globals
private constant integer ID = 039;A000039; //Raw ID of the Passive Skill
private constant integer SUB_ID = 039;A001039; //Raw ID of the Target Skill
private constant integer DUMMY = 039;u001039; //Raw ID of the Dummy Unit
private constant integer EDGES = 5 //Max. allowed Components
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC //Attacktype
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC //Damagetype
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS //Weapontype
private constant real BAIL = 120. //Distance from Dummy to Caster
private constant real ANGLES = 360. //360 Degrees (CAN be changed, but leave it as it is for a good result)
private constant string SFX = "Abilities\\Spells\\Human\\Polymorph\\PolyMorphDoneGround.mdl" //Impact Effect
private constant string ERRORMSG= "Unable to cast. No Compounds found." //Error message
private Data array UserData //Global struct array
endglobals
struct Data
private method Rotation_Speed takes nothing returns real //Dummy Rotation Speed
return 5.
endmethod
private method Chance takes nothing returns integer //Chance of Reduction // Counter Part for Oxidation
return 50
endmethod
private method Reduce takes nothing returns real //Reduction
return .25 - (.05 * .Level)
endmethod
private method Empower takes nothing returns real //Oxidation
return .15 + (.05 * .Level)
endmethod
private method Damage takes nothing returns real //Damage per Compound
return (30. + (5. * .Level)) * .Max
endmethod
private method Move_Speed takes nothing returns real //Move Speed of Missle
return 17.
endmethod
private method Scale takes nothing returns real //Scale of Missle
return (.85 * .Max)
endmethod
//===========================================================================
unit Caster
unit Target
unit Missle
unit array Dummy [EDGES]
real array Angles[EDGES]
real Distance
integer Level
integer Max
boolean IsCast
boolean IsActive
static method create takes unit c returns Data
local integer Pui = GetUnitIndex(c)
local Data this = Data.allocate()
local trigger OnCast = CreateTrigger()
local trigger SubCast = CreateTrigger()
local trigger CheckCast = CreateTrigger()
set .Caster = c
set .Max = 0
set .IsCast = false
set .IsActive = false
call TriggerRegisterUnitEvent(OnCast,.Caster,EVENT_UNIT_SPELL_EFFECT)
call TriggerAddCondition(OnCast,Condition(function Data.OnCast_Conditions))
call TriggerAddAction(OnCast,function Data.OnCast_Actions)
call TriggerRegisterUnitEvent(CheckCast,.Caster,EVENT_UNIT_SPELL_CAST)
call TriggerAddCondition(CheckCast,Condition(function Data.SubCast_Conditions))
call TriggerAddAction(CheckCast,function Data.CheckCast_Actions)
call TriggerRegisterUnitEvent(SubCast,.Caster,EVENT_UNIT_SPELL_EFFECT)
call TriggerAddCondition(SubCast,Condition(function Data.SubCast_Conditions))
call TriggerAddAction(SubCast,function Data.SubCast_Actions)
set OnCast = null
set CheckCast = null
set SubCast = null
set UserData[Pui] = this
return this
endmethod
static method OnCast_Conditions takes nothing returns boolean
return GetSpellAbilityId() != SUB_ID
endmethod
static method OnCast_Timer takes nothing returns boolean
local Data this = TT_GetData()
local real CasterX = GetUnitX(.Caster)
local real CasterY = GetUnitY(.Caster)
local real X
local real Y
local integer Count = 0
if .Distance <= BAIL then
set .Distance = .Distance + .Rotation_Speed()
endif
if IsUnitType(.Caster,UNIT_TYPE_DEAD) == true then
loop
exitwhen Count >= .Max
set Count = Count + 1
call KillUnit(.Dummy[Count])
endloop
set .Max = 0
set .IsActive = false
return true
else
loop
exitwhen Count >= .Max
set Count = Count + 1
set .Angles[Count] = .Angles[Count] + .Rotation_Speed() * bj_DEGTORAD
set X = CasterX + .Distance * Cos(.Angles[Count])
set Y = CasterY + .Distance * Sin(.Angles[Count])
call SetUnitX(.Dummy[Count],X)
call SetUnitY(.Dummy[Count],Y)
call SetUnitFacing(.Dummy[Count],.Angles[Count] * bj_RADTODEG)
endloop
if .IsCast == true then
return true
endif
endif
return false
endmethod
static method OnCast_Actions takes nothing returns nothing
local Data this = UserData[GetUnitIndex(GetTriggerUnit())]
local real CasterX
local real CasterY
local real X
local real Y
local integer Count = 0
if .IsCast == false and .Max < EDGES then
set .Max = .Max + 1
set .Distance = 0
set .Level = GetUnitAbilityLevel(.Caster,ID)
set CasterX = GetUnitX(.Caster)
set CasterY = GetUnitY(.Caster)
loop
exitwhen Count >= .Max
set Count = Count + 1
set .Angles[Count] = Count * ANGLES/.Max * bj_DEGTORAD
if Count == .Max then
set X = CasterX + .Distance * Cos(.Angles[Count])
set Y = CasterY + .Distance * Sin(.Angles[Count])
set .Dummy[Count] = CreateUnit(GetOwningPlayer(.Caster),DUMMY,X,Y,.Angles[Count] * bj_RADTODEG)
endif
endloop
if .IsActive == false then
call TT_Start(function Data.OnCast_Timer,this)
set .IsActive = true
endif
endif
endmethod
static method SubCast_Conditions takes nothing returns boolean
return GetSpellAbilityId() == SUB_ID
endmethod
static method SubCast_Timer takes nothing returns boolean
local Data this = TT_GetData()
local real DX = GetUnitX(.Missle)
local real DY = GetUnitY(.Missle)
local real TX = GetUnitX(.Target)
local real TY = GetUnitY(.Target)
local real Angle = Atan2(TY - DY,TX - DX)
local real X = DX + .Move_Speed() * Cos(Angle)
local real Y = DY + .Move_Speed() * Sin(Angle)
local real DistX = TX - DX
local real DistY = TY - DY
local real Dist = SquareRoot(DistX * DistX + DistY * DistY)
call SetUnitX(.Missle,X)
call SetUnitY(.Missle,Y)
call SetUnitFacing(.Missle,Angle * bj_RADTODEG)
if Dist <= .Move_Speed() then
call KillUnit(.Missle)
set .IsActive = false
set .IsCast = false
call DestroyEffect(AddSpecialEffect(SFX,X,Y))
if GetRandomInt(1,100) <= .Chance() then
call UnitDamageTarget(.Caster,.Target,.Damage() - ( .Damage() * .Reduce() ),true,true,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
else
call UnitDamageTarget(.Caster,.Target,.Damage() + ( .Damage() * .Empower() ),true,true,ATTACK_TYPE,DAMAGE_TYPE,WEAPON_TYPE)
endif
set .Max = 0
return true
endif
return false
endmethod
static method SubCast_Actions takes nothing returns nothing
local Data this = UserData[GetUnitIndex(GetTriggerUnit())]
local real CasterX = GetUnitX(.Caster)
local real CasterY = GetUnitY(.Caster)
local real TargetX
local real TargetY
local real X
local real Y
local real Angle
local integer Count = 0
set .IsCast = true
set .Target = GetSpellTargetUnit()
set TargetX = GetUnitX(.Target)
set TargetY = GetUnitY(.Target)
set Angle = Atan2(TargetY - CasterY,TargetX - CasterX)
set X = CasterX + BAIL * Cos(Angle)
set Y = CasterY + BAIL * Sin(Angle)
loop
exitwhen Count >= .Max
set Count = Count + 1
call KillUnit(.Dummy[Count])
endloop
set .Missle = CreateUnit(GetOwningPlayer(.Caster),DUMMY,X,Y,Angle)
call SetUnitScale(.Missle,.Scale(),.Scale(),.Scale())
call TT_Start(function Data.SubCast_Timer,this)
endmethod
static method CheckCast_Actions takes nothing returns nothing
local Data this = UserData[GetUnitIndex(GetTriggerUnit())]
if .Max == 0 then
call IssueImmediateOrder(.Caster,"stop")
call SimError(GetOwningPlayer(.Caster),ERRORMSG)
endif
endmethod
endstruct
private function Conditions takes nothing returns boolean
local unit Learning = GetLearningUnit()
local integer Pui = GetUnitIndex(Learning)
if GetLearnedSkill() == ID and GetUnitAbilityLevel(Learning,ID) == 1 then
set UserData[Pui] = UserData[Pui].create(Learning)
call UnitAddAbility(Learning,SUB_ID)
endif
if GetLearnedSkill() == ID and GetUnitAbilityLevel(Learning,ID) >= 1 then
call SetUnitAbilityLevel(Learning,SUB_ID,GetUnitAbilityLevel(Learning,ID))
endif
set Learning = null
return false
endfunction
//===========================================================================
private function Init takes nothing returns nothing
local trigger Trig = CreateTrigger( )
call Preload(SFX)
call TriggerRegisterAnyUnitEventBJ( Trig, EVENT_PLAYER_HERO_SKILL )
call TriggerAddCondition( Trig, Condition( function Conditions ) )
set Trig = null
endfunction
endscope
As usual, i don't care about credits, but don't claim this as your own.
Any comments?