| 02-28-2008, 09:45 AM | #1 |
v 1.1 This was a submitted system in the resource forum but because of the lot of limitations it has it was suggested to be moved here, so I can improve it until it is finally ready for another try. This is a DOT system that allows you to damage a unti over time if it has a specific buff. As for now, you can read how it works in the implementation instruction. I need your ideas so this can be improved, stretchened, or whatever you want it, so users can use it freely and with ease. Reasonable suggestions will be considered and if are useful enough I'll try to add them if they fit in my jass abilities (I'm not a very skilled jasser). Requires: - JASS NewGen Editor - ABCT v2.0 (or higher) - PUI v4.2 (or higher) Implementation Instructions: JASS://====================================================================== ======== // Damage Over Time System [v 1.1] by cr4xzZz //====================================================================== ======== ' PURPOSE: - Creating damage over time spells the easy way - Save time on damage over time spells ' HOW IT WORKS: - When you call the start function ( DOT_Start() ) a periodic timer will run every 0.1 seconds for 5 seconds, checking each period if the target has the assigned buff you chose. If in that time the target is applied the buff then DOT starts with all the values you used. If the target does not recieve that buff on time (5 secs) then the function is cancelled. These values can be changed to satisfy your needs (look for a comment in the globals in the DOT trigger). - After the normal damaging starts the system checks if the target has the assigned buff each time before it damages it. If the target does not have that buff then the damaging stops. The system stops if the buff is dispelled, too (obviously). - The system attaches all values to array globals thanks to PUI. That way they can easily be used for Set and Get functions. ' HOW TO USE: - call DOT_Start( DAMAGER, TARGET, PERIOD, DURATION, BUFF, DAMAGE, ATTACK TYPE, DAMAGE TYPE, MELEE?, RANGED?, EFFECT, ATTACHMENT POINT) * DAMAGER - unit; The unit that is going to damage something * TARGET - unit; The target unit that is going to be damaged * PERIOD - real; Period per damaging * DURATION - real; Maximum duration of the damaging * BUFF - integer; The buff that is required for the damaging to work // raw code ! //! IF THE TARGET DOES NOT HAVE THAT //! BUFF THEN THE DAMAGING STOPS * DAMAGE - real; The damage dealt per each period //! NOTE THAT THIS IS NOT THE MAX DAMAGE * ATTACK TYPE - attacktype; The attack type of the damaging * DAMAGE TYPE - damagetype; The damage type of the damaging * MELEE? - boolean; If it is a melee type damage * RANGED? - boolean; If it i s a ranged type damage // these two booleans must be true or false * EFFECT - string; Special effect string * ATTACHMENT POINT - string; The attachment point of the special effect ' OTHER FUNCTIONS: //! Note that these functions work only on the TARGET //! and NOT on the DAMAGER ! This means that the //! unit argument should be a TARGET that has DOT //! on it. - call DOT_SetDamage(unit TARGET, real AMOUNT) - call DOT_SetDuration(unit TARGET, integer AMOUNT) - call DOT_SetAttackType(unit TARGET, attacktype ATTACK TYPE) - call DOT_SetDamageType(unit TARGET, damagetype DAMAGE TYPE) // this must be true or false - call DOT_SetMelee(unit TARGET, boolean MELEE?) // this must be true or false - call DOT_SetRange(unit TARGET, boolean RANGED?) - call DOT_SetEffect(unit TARGET, string EFFECT) - call DOT_SetAttachmentPoint(unit TARGET, string ATTACHMENT POINT) - call DOT_GetDamage(unit TARGET) -> real AMOUNT - call DOT_GetDuration(unit TARGET) -> integer AMOUNT - call DOT_GetAttackType(unit TARGET) -> attacktype ATTACK TYPE - call DOT_GetDamageType(unit TARGET) -> damagetype DAMAGE TYPE - call DOT_GetMelee(unit TARGET) -> boolean MELEE? - call DOT_GetRange(unit TARGET) -> boolean RANGED? - call DOT_GetEffect(unit TARGET) -> string EFFECT - call DOT_GetAttachmentPoint(unit TARGET) -> string ATTACHMENT POINT - call DOT_Stop(unit TARGET) // stop all assigned DOT functions - call DOT_AddDuration(unit TARGET, integer AMOUNT) // add more duration to the damaging ' PROS: - Easy to use - A lot customizeable - Can be fully controlled ' CONS: - None? (cannot think of any...) ' HOW TO IMPLEMENT: - Copy the ABCT and PUI systems if you do not have them - Copy the DOT trigger in your map ' CREDITS TO: - Cohadar for ABCT v2.0 and PUI v4.2 ' CHANGELOG: - v1.0: First release - v1.1: No changes at all. Just uses the newest version of ABCT (v 2.0) Code: JASS://============================================================================== // Damage Over Time System [v 1.1] by cr4xzZz //============================================================================== library DOT uses ABCT, PUI globals private real array DPP private integer array DURATION private attacktype array ATTACK private damagetype array DAMAGE private string array EFFECT private string array POINT private boolean array MELEE private boolean array RANGE // - Can be configured - private constant real CHECK_PERIOD = 0.1 //period for buff checkup private constant real MAX_CHECK_TIME = 5. //max wait time for buff checkup endglobals // - DO NOT change anything below this line !!! - private struct SysStruct unit damager unit target real period integer buffz integer temp timer clock = CreateTimer() static method create takes unit whichUnit, unit whichTarg, integer whichBuff, real whichPeriod returns SysStruct local SysStruct data = SysStruct.allocate() set data.damager = whichUnit set data.target = whichTarg set data.buffz = whichBuff set data.period = whichPeriod set data.temp = R2I(MAX_CHECK_TIME / CHECK_PERIOD) return data endmethod method onDestroy takes nothing returns nothing set DURATION[GetUnitIndex(.target)] = 0 call PauseTimer(.clock) call DestroyTimer(.clock) endmethod endstruct // - - - - - SET FUNCTIONS - - - - - public function SetDamage takes unit whichUnit, real whichDmg returns nothing set DPP[GetUnitIndex(whichUnit)] = whichDmg endfunction public function SetDuration takes unit whichUnit, integer whichInt returns nothing if whichInt > 0 then set DURATION[GetUnitIndex(whichUnit)] = whichInt else //debug call BJDebugMsg("|cffffcc00[DOT] -|r Cannot use <= 0 in SetDuration(). Use Stop() instead") endif endfunction public function SetAttackType takes unit whichUnit, attacktype whichAttackType returns nothing set ATTACK[GetUnitIndex(whichUnit)] = whichAttackType endfunction public function SetDamageType takes unit whichUnit, damagetype whichDamageType returns nothing set DAMAGE[GetUnitIndex(whichUnit)] = whichDamageType endfunction public function SetMelee takes unit whichUnit, boolean whichBool returns nothing set MELEE[GetUnitIndex(whichUnit)] = whichBool endfunction public function SetRanged takes unit whichUnit, boolean whichBool returns nothing set RANGE[GetUnitIndex(whichUnit)] = whichBool endfunction public function SetEffect takes unit whichUnit, string whichFx returns nothing set EFFECT[GetUnitIndex(whichUnit)] = whichFx endfunction public function SetAttachmentPoint takes unit whichUnit, string whichPoint returns nothing set POINT[GetUnitIndex(whichUnit)] = whichPoint endfunction // = = = = = = = = = = = = = = = = = = = = = = = = = = // - - - - - GET FUNCTIONS - - - - - public function GetDamage takes unit whichUnit returns real return DPP[GetUnitIndex(whichUnit)] endfunction public function GetDuration takes unit whichUnit returns integer return DURATION[GetUnitIndex(whichUnit)] endfunction public function GetAttackType takes unit whichUnit returns attacktype return ATTACK[GetUnitIndex(whichUnit)] endfunction public function GetDamageType takes unit whichUnit returns damagetype return DAMAGE[GetUnitIndex(whichUnit)] endfunction public function GetMelee takes unit whichUnit returns boolean return MELEE[GetUnitIndex(whichUnit)] endfunction public function GetRange takes unit whichUnit returns boolean return RANGE[GetUnitIndex(whichUnit)] endfunction public function GetEffect takes unit whichUnit returns string return EFFECT[GetUnitIndex(whichUnit)] endfunction public function GetAttachmentPoint takes unit whichUnit returns string return POINT[GetUnitIndex(whichUnit)] endfunction // = = = = = = = = = = = = = = = = = = = = = = = = = = public function Stop takes unit whichUnit returns nothing set DURATION[GetUnitIndex(whichUnit)] = 0 //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT stops") endfunction public function AddDuration takes unit whichUnit, integer whichInt returns nothing set DURATION[GetUnitIndex(whichUnit)] = DURATION[GetUnitIndex(whichUnit)] + whichInt endfunction private function Damage takes nothing returns boolean local SysStruct data = ABCT_GetData() local integer pui = GetUnitIndex(data.target) if GetWidgetLife(data.target) >= 0.405 and GetUnitAbilityLevel(data.target, data.buffz) > 0 and DURATION[pui] > 0 then call UnitDamageTarget(data.damager, data.target, DPP[pui], MELEE[pui], RANGE[pui], ATTACK[pui], DAMAGE[pui], null) call DestroyEffect(AddSpecialEffectTarget(EFFECT[pui], data.target, POINT[pui])) else call data.destroy() //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT finishes") return true endif set DURATION[pui] = DURATION[pui] - 1 return false endfunction private function Check takes nothing returns boolean local SysStruct data = ABCT_GetData() if GetUnitAbilityLevel(data.target, data.buffz) > 0 then call ABCT_Start(function Damage, data, data.period) //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT starts") return true endif set data.temp = data.temp - 1 if data.temp <= 0 then call data.destroy() //debug call BJDebugMsg("|cffffcc00[DOT] -|r DOT cancelled") return true endif return false endfunction public function Start takes unit whichUnit, unit whichTarg, real whichPeriod, real whichDur, integer whichBuff, real whichDmg, attacktype whichAttackType, damagetype whichDamageType, boolean isMelee, boolean isRange, string whichFx, string whichPoint returns nothing local SysStruct data = SysStruct.create(whichUnit, whichTarg, whichBuff, whichPeriod) local integer pui = GetUnitIndex(data.target) set DPP[pui] = whichDmg set DURATION[pui] = DURATION[pui] + R2I((1. / whichPeriod) * whichDur) set ATTACK[pui] = whichAttackType set DAMAGE[pui] = whichDamageType set MELEE[pui] = isMelee set RANGE[pui] = isRange set EFFECT[pui] = whichFx set POINT[pui] = whichPoint call ABCT_Start(function Check, data, CHECK_PERIOD) endfunction endlibrary Test map includes Acid Bomb and Frost Nova ability tests (for the buffs). Changelog: v1.0 - First release v1.1 - Absolutely no changes. Just uses the newest version of ABCT - v2.0 |
| 02-28-2008, 09:54 AM | #2 |
It's so stretched because you have an extra long line: "public function Start takes...". |
| 02-28-2008, 10:07 AM | #3 |
> It's so stretched because you have an extra long line: "public function Start takes...". Oh, right... ^^ Comments anybody? |
| 02-29-2008, 02:57 PM | #4 | |
You've got some weird things going on here. JASS:...boolean isMelee, boolean isRange... Also, what exactly is the point of your melee and ranged booleans that you store? They do nothing in the UnitDamageTarget() call as far as I am concerned, and they just add unnecessary arguments to your sample's function call. Quote:
I also don't see the value of requiring the buff in the first place. I mean, if I know my DOT is supposed to last 12 seconds and I want to deal damage once every 0.5 seconds, I don't need anything else. If I want a buff, I can make one and add it for 12 seconds, but I don't need one. Really, because of that huge limitation, you've made this absolutely un-approvable. Also, your DOT_AddDuration thing is impractical because it doesn't even increase the duration of the buff you require! What good is that since your system ends when the buff ends anyways! Also, your implementation instructions are terribly hard to read. Do us all a favor and make the entire thing in comments so it's at least the same color. You also should implement safety for if I use a blank string for the effect. What if I don't want an effect to play when I damage them per interval? You should at least add a check in your Periodic function to ensure that you're not creating effects without given paths. (It's good coding practice to be safe) The same applies for your POINT vars. EDIT: One more thing I find a critical flaw in your system. There is no way to know what type of damage or what attack type is being used for a given damage. Your system resets a unit's damagetype/attacktype every time you call the DOT_Start function, so I lose all information about the last damage call I made. Also, your DOT_AddDuration function AGAIN only applies to the last created damage periodic! That's TERRIBLE! What if I want to add some duration to one of my DOT spells but not to them all? I can't do that with how you've set up your system. This can hardly even be considered a system with how many limitations and shortcomings it has. I'd rather use ABuff for everything and just use a generic damage buff, it'd not only be easier but also more malleable. This needs A LOT of work to be in a state that I can allow it to be approved. |
| 02-29-2008, 03:38 PM | #5 |
I agree with Rising_Dusk in all except in the buff statement. IMHO every Dot spell should be buff based, because if you have buff it can be dispelled or purged. |
| 02-29-2008, 04:34 PM | #6 |
In my opinion dispell and purge abilities should be purged from every map for being lame, so that isn't an issue in my opinion, and is in fact GOOD because buffs can be iffy with conflicts, recasts, etc. Full and proper MUI isn't possible with Blizzard's lame buffs. |
| 02-29-2008, 05:10 PM | #7 | |
Quote:
Absolutely not true. Dispel adds tactical depth to some combats, conflicts, recasts and similar can all be handled with a proper coding, and full and proper MUI is 10 times easier with buffs than with attaching only. I base my spells around blizzards native buffs all the time and it works great. Just look at the "Rejuvenation Shield" from Pyramidal Defence, it is one of the best spells I made. It works with recasts (it stacks based on caster level) and it can be dispelled. So your claims are from the simple fact that you would rather be lazy than do a proper spell coding. |
| 02-29-2008, 05:32 PM | #8 |
And in melee games, dispelling is a must have for any race in order to keep the balance. Honestly I've been a little bit busy, so I haven't seen the code in depth, I'll give a review this weekend if my body can resist the real life. |
| 02-29-2008, 09:34 PM | #9 | ||
Quote:
Quote:
|
| 03-02-2008, 11:06 AM | #10 |
Oh well... This was supposed to be a simple dot system because I do not have much experience in jass. Now that you mentioned 100 bugs that I didn't found this "system" really seems pointless. :\ I give up. |
| 03-02-2008, 02:27 PM | #11 |
You shouldn't give up, you should just aim to make things as globally interactive as possible. I can move this to triggers and scripts for you to seek out ways to improve your work and make it more useful, if you'd like. |
| 03-02-2008, 03:17 PM | #12 |
> I can move this to triggers and scripts for you to seek out ways to improve your work and make it more useful, if you'd like. Well, ok. Sounds fine I guess ^^ |
| 03-02-2008, 03:31 PM | #13 |
As you wish. Moved. |
| 03-03-2008, 06:55 PM | #14 |
Since I have no idea where to start, I'd like some tips. First of all, I'd like to know what would be the best way to make Set functions work for each Start function? As noted a few posts above, the Set functions have the flaw to set information on the last started DOT function. This means that if a unit has 3 DOT calls on it, the Set functions will work only on the last called one! |
| 03-04-2008, 03:09 AM | #15 |
Why have any "set" functions at all? Wouldn't it make more sense to just have people declare the damage/attacktype upon starting the function? |
