| 12-20-2005, 05:45 AM | #1 |
Generic Damage JASS://*********** // Constants: //*********** constant function GenericDamage_DamageDetector takes nothing returns integer return 'A005' //This is the orb ability that ALL units will be given when the system is //initialized and when new units arrive into the game endfunction constant function GenericDamage_DamageDetectorBuff takes nothing returns integer return 'B001' //This is the buff the orb ability will give to attacked units, and will be //detected by the system endfunction //***************** // Public Function: //***************** function GenericDamage_DummyDamage takes unit whichUnit, string whichState returns nothing if whichState=="Ignore" then call SetTableInt("[DamageDummy]_" + GetAttachmentTable(whichUnit), "DamageDummy", 1) elseif whichState=="Allow" then call DestroyTable("[DamageDummy]_" + GetAttachmentTable(whichUnit)) endif endfunction function GetDamageEventCause takes nothing returns string return GetTableString("[GenericDamage_State]","DamageType") endfunction //****************** // Private Function: //****************** function GenericDamage_DamageTaken takes nothing returns nothing local integer i local integer c=1 local string funcName if (not HaveStoredInteger(udg_cscache, "[DamageDummy]_" + GetAttachmentTable(GetEventDamageSource()), "DamageDummy")) then if GetUnitAbilityLevel(GetTriggerUnit(), GenericDamage_DamageDetectorBuff()) > 0 then //For use SPECIFICALLY for attacks call UnitRemoveAbility(GetTriggerUnit(), GenericDamage_DamageDetectorBuff()) set c=1 call SetTableString("[GenericDamage_State]","DamageType", "ATTACK") set i=GetTableInt("[GenericDamage_Table]", "FuncCountAttack") loop exitwhen c > i set funcName=GetTableString("[GenericDamage_Table]", "AttackFunc_" + I2S(c)) call ExecuteFunc(funcName) set c=c+1 endloop else //For use SPECIFICALLY for any other damage call SetTableString("[GenericDamage_State]","DamageType", "SPELL") set i=GetTableInt("[GenericDamage_Table]", "FuncCount") set c=1 loop exitwhen c > i set funcName=GetTableString("[GenericDamage_Table]", "Func_" + I2S(c)) call ExecuteFunc(funcName) set c=c+1 endloop endif endif endfunction //***************** // Public Function: //***************** function GenericDamage_QueueFuncBySpell takes string funcName returns nothing //******************************************************************************************** // Info: This function queues the system to detect triggered/spell damage. You can force it to // ignore certain damage by using a dummy unit and setting an integer under the table // "[DamageDummy]_" + GetAttachmentTable(DUMMY), "DamageDummy". Any units who deal damage // with the ignore integer under this heading set to a value. Flushing or destroying that // that table will allow damage dealt by that dummy to be registered again //******************************************************************************************** local integer i=GetTableInt("[GenericDamage_Table]", "FuncCount") + 1 call SetTableString("[GenericDamage_Table]", "Func_" + I2S(i), funcName) call SetTableInt("[GenericDamage_Table]", "FuncCount", i) //call DisplayTimedTextToPlayer(Player(0), 0, 0, 5, "Function Queued: " + funcName + " in slot " + I2S(i)) //DEMO ADDITION - Use to check that its working right endfunction //***************** // Public Function: //***************** function GenericDamage_QueueFuncByAttack takes string funcName returns nothing //******************************************************************************************** // Info: This function queues the given function to register attack damage. This requires a weak // method using a stupid Orb Effect. Lame.... //******************************************************************************************** local integer i=GetTableInt("[GenericDamage_Table]", "FuncCountAttack") + 1 call SetTableString("[GenericDamage_Table]", "AttackFunc_" + I2S(i), funcName) call SetTableInt("[GenericDamage_Table]", "FuncCountAttack", i) //call DisplayTimedTextToPlayer(Player(0), 0, 0, 5, "Function Queued: " + funcName + " in slot " + I2S(i)) //DEMO ADDITION - Use to check that its working right endfunction //******************* // Private Functions: //******************* function GenericDamage_AddTriggers takes nothing returns nothing local trigger dmgtrigger = CreateTrigger() local string s=GetAttachmentTable(dmgtrigger) call TriggerRegisterUnitEvent(dmgtrigger, GetTriggerUnit(),EVENT_UNIT_DAMAGED) call UnitAddAbility(GetTriggerUnit(), GenericDamage_DamageDetector()) call SetTableObject(s,"action",TriggerAddAction(dmgtrigger,function GenericDamage_DamageTaken)) call SetTableObject("damagesystem_" + GetAttachmentTable(GetTriggerUnit()),"dmgTrigger",dmgtrigger) endfunction function GenericDamage_RemoveTriggers takes nothing returns nothing local trigger me=GetTableTrigger("damagesystem_" + GetAttachmentTable(GetTriggerUnit()),"dmgTrigger") call TriggerRemoveAction(me,GetTableTriggerAction(GetAttachmentTable(me),"action")) call DestroyTrigger(me) call DestroyTable(GetAttachmentTable(me)) set me=null endfunction function GenericDamage_InitializeSystem takes nothing returns nothing local trigger entermap=CreateTrigger() local group g=CreateGroup() local unit u local trigger dmgtrigger local trigger upondeath=CreateTrigger() local string s call GroupEnumUnitsInRect(g,bj_mapInitialPlayableArea,null) loop set u=FirstOfGroup(g) exitwhen u==null set dmgtrigger=CreateTrigger() set s=GetAttachmentTable(dmgtrigger) call UnitAddAbility(u, GenericDamage_DamageDetector()) call TriggerRegisterUnitEvent(dmgtrigger,u,EVENT_UNIT_DAMAGED) call SetTableObject(s,"action",TriggerAddAction(dmgtrigger,function GenericDamage_DamageTaken)) call SetTableObject(s,"dmgTrigger",dmgtrigger) call GroupRemoveUnit(g,u) endloop call TriggerRegisterEnterRectSimple(entermap, bj_mapInitialPlayableArea) call TriggerAddAction(entermap,function GenericDamage_AddTriggers) call TriggerRegisterAnyUnitEventBJ(upondeath,EVENT_PLAYER_UNIT_DEATH) call TriggerAddAction(upondeath,function GenericDamage_RemoveTriggers) set dmgtrigger=null set g=null set upondeath=null endfunction ----------------------------------------------------------------------- Now that we have our generic damage detection set up(and having called InitializeSystem apon map initialization) we can now create a spell that works on it. This is an orb effect I am using for DoD JASS:
//####################################################################################\\
// Spell Name: Orb of Lifesteal \\
// Spell Author: Chuckle_Brother \\
//####################################################################################\\
//################################################################\\
// \\
// Configuration Section \\
// \\
//################################################################\\
constant function Trig_OrbLifeSteal_ItemId takes nothing returns integer
return 'I001'
endfunction
constant function Trig_OrbLifeSteal_LifeStolen takes integer itemCount returns real
return 0.1 + (0.02 * (itemCount - 1))
endfunction
constant function Trig_OrbLifeSteal_SpecialEffect takes nothing returns string
return "Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl"
endfunction
//################################################################\\
// \\
// Spell Section \\
// \\
//################################################################\\
function Trig_OrbLifeSteal_Acts takes nothing returns nothing
local integer i
local unit damaged=GetTriggerUnit()
local unit damager=GetEventDamageSource()
local real toDrain
set i=CountItemsOfType(damager, Trig_OrbLifeSteal_ItemId())
if i > 0 and GetEventDamage() > 0 then
set toDrain=Trig_OrbLifeSteal_LifeStolen(i) * GetEventDamage()
call SetUnitState(damager, UNIT_STATE_LIFE, GetUnitState(damager, UNIT_STATE_LIFE) + toDrain)
call DestroyEffect(AddSpecialEffectTarget(Trig_OrbLifeSteal_SpecialEffect(), damager, "origin"))
endif
set damaged=null
set damager=null
endfunction
//===========================================================================
function InitTrig_Orb_of_Lifesteal takes nothing returns nothing
call GenericDamage_QueueFuncByAttack("Trig_OrbLifeSteal_Acts")
endfunctionEnjoy! Edit: I finally fixed this tutorial, no more silly errors :) |
| 01-15-2006, 08:59 PM | #2 | |
Two things: Why wouldn't you want to resort to a "cheesy 'Unit Is Attacked' event"? There's probably something I'm missing here, but it might be good to mention for people like me ^^ and: Quote:
After a few hundred events or so, performance starts to degrade. At least, that's what I've seen. |
| 01-16-2006, 04:08 AM | #3 |
First off, using "Unit is Attacked" is tantamount to rushing outside to declare yourself a noob. It activates before the unit even finishes its attack animation, and spells based off it tend to look pretty haphazard. Also if a unit is attacked but the attack misses you can still gain the effects of the triggers, and you can attack and continue to cancel and still gain the triggered effects. |
| 01-16-2006, 05:31 AM | #4 |
Use trigger tags: http://www.wc3campaigns.net/showthread.php?t=78403. EDIT: Using bash is a bad idea, there are other, better buff spells, this will stop all channeling spells with one single attack, can destroy balance of a map. |
| 01-16-2006, 02:01 PM | #5 |
Well, that makes sense, but couldn't you just wait a second or so on the trigger to sync it with animation and make sure it's taken damage? I haven't really done much with unit is attacked so I don't know this stuff :P Enlighten me :D |
| 01-17-2006, 12:24 PM | #6 | |
Quote:
You can use anything, I used bash because my spell is intended to stun then, the only problem I found is: 1) You can't hide some Orb spells 2) Some Orb spells aren't so well synced. @Johnfn...well that's all fine and well when you only have a single unit running the spell, but if you want more unit's to be able to use it, or you want to do anything involving damage dealt, you CANNOT use "Unit is Attacked" @Blade, yeah, I put this up before I knew the trigger tags were implemented. |
| 01-17-2006, 03:11 PM | #7 |
Frost Orb is the best to use, it has no icon, and it has no side effects on applying the buff (bash inturrupts spellcasting) the big downside is that you cannot use any other orb/arrow/attack modification abilities, although i am sure that it can be triggered using the attack detection method. |
| 01-17-2006, 05:22 PM | #8 |
This method leaks events when units die |
| 01-19-2006, 12:39 PM | #9 |
Damns, well how can I be fixing this? How can you remove events from a trigger? Unless I will have to create triggers through jass then destroy and nullify them constantly as units die. Help anyone? Also if I have to do that how am I to be saving the triggers in variables, I assume through attachable variables...which I haven't used yet, so yeah help. |
| 01-19-2006, 02:55 PM | #10 | |
Quote:
|
| 01-19-2006, 03:27 PM | #11 |
Alright then, so I guess its time to learn how to use attachable variables and whatnot. |
| 01-20-2006, 05:56 PM | #12 |
Okay, I have been trying to do this...and I keep failing miserably. So anyone who can help please do. Oh and @Vex, does the regexp in your siggy refer to Regular Expressions as used in Linux and such? |
| 01-20-2006, 06:10 PM | #13 |
and php |
| 01-21-2006, 03:24 AM | #14 |
Oh fun stuff, I'm currently doing it in Unix/Linux, boring but necessary I guess. Alright so I can't get the attachment to work, it gives an error like "Type Mismatch" or somesuch, does not a trigger go under AttachObject? |
| 01-21-2006, 11:31 AM | #15 |
Yeah, but to get it you need GetAttachedTrigger |
