| 08-20-2009, 05:17 PM | #1 |
For an RPG game I'm working on, I used moyack's damage detection system to create a system that can register critical hits. And it works nicely, except for the floating text, after awhile it starts to disappear. I'm not sure if I'm incorrectly disposing of it or if I'm forgetting to add something to make it disappear. Anyways, could someone possibly take a look at my code and see what's the problem? JASS:scope CriticalHits initializer init globals private constant real factor = 1.5 // multiplier damage factor private constant attacktype AT = ATTACK_TYPE_HERO // Sets the Attack type for Physical Attacks/Spells private constant damagetype DT = DAMAGE_TYPE_NORMAL // Sets the Damage type for Attacks/Spells private constant attacktype MagAT = ATTACK_TYPE_NORMAL // Sets the Damage Type for Magical Spells private constant real CritReducedPerArmor = .005 //Sets how much Critical Chance is reduced by when the target upgrades Armor private constant real NBonusCrit_PerLevDiff = .1 //Sets how the amount of Bonus Critical Hit Chance a Normal Monster recieves b/t level differences private constant real BBonusCrit_PerLevDiff = .2 //Sets how the amount of Bonus Critical Hit Chance a Boss Monster recieves b/t level differences endglobals private struct data unit u unit c real damage boolean crit static method create takes unit u, unit c, real damage, boolean crit returns data local data d = data.allocate() set d.u = u set d.c = c set d.damage = damage set d.crit = crit return d endmethod endstruct private struct text_dat texttag t static method create takes texttag t returns text_dat local text_dat d = text_dat.allocate() set d.t = t return d endmethod endstruct private function delete_text takes nothing returns nothing local text_dat d = text_dat(GetTimerData(GetExpiredTimer())) call DestroyTextTag(d.t) call d.destroy() call ReleaseTimer(GetExpiredTimer()) endfunction private function critical takes nothing returns nothing local data d = data(GetTimerData(GetExpiredTimer())) local real r = 0 local real damage = 0 local real l = GetWidgetLife(d.u) call d.destroy() call ReleaseTimer(GetExpiredTimer()) set damage = d.damage * (factor) set damage = damage - d.damage if d.crit == true then call DoNonDetectableDamage(d.c, d.u,damage, true, false, AT, DT, WEAPON_TYPE_WHOKNOWS) //If the Wizard knows the Fire Ability: Enduring Flames, any critical hit that he does //will take 50% of that damage and burn the target for that damage over 8 seconds //Example: Wizard crits for 50! The target will take 25 extra damage over 8 seconds //Enduring Flames AbilityId is 'A01B' if GetUnitAbilityLevel(d.c,'A01B')>0 then set r = d.damage * (factor) set r = r*.5 set r = r*.125 call UnitDamageUnitTimed(d.c,1.,r,8.,d.u,MagAT,DT) call AddSpecialEffectTargetUnitWithTimer("head",d.u,"Abilities\\Spells\\Human\\FlameStrike\\FlameStrikeDamageTarget.mdl",8) endif endif endfunction private function DoEffect takes nothing returns boolean local real d = GetEventDamage()// Damage dealt normally local unit u = GetTriggerUnit()// unit that receives the damage local real l = GetWidgetLife(u)// unit life local unit c = GetEventDamageSource()// unit that deals the damage local player p = GetOwningPlayer(c) local player pu = GetOwningPlayer(u) local texttag t local real chance local integer lev_diff local timer tm local boolean crit local string msg if d<=.405 then return false endif if GetPlayerController(p)==MAP_CONTROL_USER then set chance = .05 //The Warrior Requires Dexterity upgrades to enhance his Critical Chance //The Wizard Requires Magic upgrades to enhance his Critical Chance //The Thief Requires Dexterity upgrades to enhance his Critical Chance if GetUnitTypeId(c)=='H000' then //Warrior set chance = chance + (.01*GetPlayerTechCount(p,'R003',true)) elseif GetUnitTypeId(c)=='H001' then //Wizard set chance = chance + (.01*GetPlayerTechCount(p,'R004',true)) elseif GetUnitTypeId(c)=='E001' then //Thief set chance = chance + (.01*GetPlayerTechCount(p,'R003',true)) endif if UnitHasBuffBJ(c,'B004') then //If Unit has Dark Vigor, increase their critical chance set chance = chance + .2 endif //If a Hero upgraded their armor, their chance to take a Critical Hit //from a monster is reduced by .005 per Armor Level. //Additionally, if there's a level difference b/t a Hero and a Monster, //the monster's Critical Hit Chance will adjust accordingly. if IsUnitType(u,UNIT_TYPE_HERO)==true then set lev_diff = GetHeroLevel(c) - GetHeroLevel(u) set chance = chance + (lev_diff*BBonusCrit_PerLevDiff) set chance = chance - (CritReducedPerArmor*GetPlayerTechCount(pu,'R002',true)) endif elseif GetPlayerController(p)==MAP_CONTROL_COMPUTER then set chance = .05 //SPECIAL UNITS START //Certain monsters have a naturally higher crit chance than others //These are the following: if GetUnitTypeId(c)=='n006' then //Satyr set chance = .2 elseif GetUnitTypeId(c)=='n00G' then //Forest Wolf set chance = .2 endif //SPECIAL UNITS END //If a Hero upgraded their armor, their chance to take a Critical Hit //from a monster is reduced by .005 per Armor Level. //Additionally, if there's a level difference b/t a Hero and a Monster, //the monster's Critical Hit Chance will adjust accordingly. if IsUnitType(u,UNIT_TYPE_HERO)==true then set lev_diff = GetUnitLevel(c) - GetHeroLevel(u) set chance = chance + (lev_diff*NBonusCrit_PerLevDiff) set chance = chance - (CritReducedPerArmor*GetPlayerTechCount(pu,'R002',true)) endif endif if GetRandomReal(0,1) < chance then set crit = true set tm = NewTimer() call SetTimerData(tm, integer(data.create(u, c, d, crit))) call TimerStart(tm, 0., false, function critical) set tm = null //The following creates the TextTag (Floating Text) information for the //Critical Strike set msg = GetPlayerColorS(p)+I2S(R2I(d * factor))+"!" set t = CreateTextTag() call SetTextTagText(t,msg, 0.028) call SetTextTagPos(t, GetUnitX(u), GetUnitY(u), 0.00) call SetTextTagVelocity(t, 0, 0.06) call SetTextTagVisibility(t, true) call SetTextTagFadepoint(t, 1) call SetTextTagLifespan(t, 2) call SetTextTagPermanent(t, false) //This will attempt to destroy the texttag used. set tm = NewTimer() call SetTimerData(tm, integer(text_dat.create(t))) call TimerStart(tm, 2.01, false, function delete_text) set tm = null else set crit = false set tm = NewTimer() call SetTimerData(tm, integer(data.create(u, c, d, crit))) call TimerStart(tm, 0., false, function critical) set tm = null //The following creates the TextTag (Floating Text) information for the //Non-Critical Strike set msg = GetPlayerColorS(p)+I2S(R2I(d)) set t = CreateTextTag() call SetTextTagText(t,msg, 0.020) call SetTextTagPos(t, GetUnitX(u), GetUnitY(u), 0.00) call SetTextTagVelocity(t, 0, 0.06) call SetTextTagVisibility(t, true) call SetTextTagFadepoint(t, 1) call SetTextTagLifespan(t, 2) call SetTextTagPermanent(t, false) //This will attempt to destroy the texttag used. set tm = NewTimer() call SetTimerData(tm, integer(text_dat.create(t))) call TimerStart(tm, 2.01, false, function delete_text) set tm = null endif set t = null set u = null set c = null return false endfunction private function init takes nothing returns nothing call AddDamageCondition(Condition(function DoEffect)) endfunction endscope Thanks to any helper in advance! |
| 08-20-2009, 07:05 PM | #2 | |
Quote:
|
| 08-20-2009, 07:35 PM | #3 |
Remember that texttags allow only a limit of 99 tags showed ingame at the same time. |
| 08-20-2009, 07:48 PM | #4 | |
Quote:
This is your only hope; http://www.wc3c.net/showthread.php?t=87798 I'm going to be using an updated (for 1.24 and vJASS) version of this in my map, so once that is said and done I can share it here if you want. |
| 08-20-2009, 08:01 PM | #5 | ||
Quote:
I'm aware of that moyack, but its a Turn-based style of combat, Hero vs. Hero. So the limit shouldn't be a problem because there won't be a lot of texttag creation, and they'll be destroyed quickly. Quote:
Ooo, nice, I would greatly appreciate if you do that. |
| 08-20-2009, 09:07 PM | #6 |
I reviewed your code, and in your case, you don't need to destroy the tags because in your case you create them all the time, even if the message is null. My suggestion: don't destroy the tetxtags, they will be reused and recycled anyways. So you won't need the private struct text_dat and the timer which load that struct. |
| 08-20-2009, 09:30 PM | #7 | |
Quote:
Ahh, alright then, I'll give that a try then. Thanks moyack. |
| 08-20-2009, 11:39 PM | #8 |
Oooooh. This explains my problem, as well. I was wondering why the texttags in my map began to spontaneously disappear after a certain point in time. So... We can only have up to 100 texttags created, period? Even if we destroy them? I always thought that we could only have a certain amount of texttags appearing at the same time, but it didn't necessarily mean the amount we could use, total. But... Doesn't SetTextTagLifeSpan (I don't have the world editor right now, I don't remember the exact function name) remove the texttag from the game, though? I must have done something wrong. Hey- Kurawasa. Do you mind if you can share it with me, too? |
| 08-21-2009, 02:52 AM | #9 |
99 shown to each player at any given time, so your second statement is correct. |
| 08-22-2009, 06:19 PM | #10 |
Sorry, Moyack, but it still didnt fix the problem, I have a lot of floating text still disappearing for some reason. I thought it did work, but it didn't. : / |
| 06-09-2010, 04:57 AM | #11 |
Sorry to revive this, but that limit; if you specify visibility so that each player only sees their own generated floating texts, does that mean max 99 texts for each player or what? Also, does destroying a text tag free up space for another to be created? |
| 06-09-2010, 05:13 AM | #12 |
First one: they might cause a desync to create them locally (don't quote me on that), second one: yes, destroying them/having them "expire" frees up space for more. |
| 06-09-2010, 05:24 AM | #13 |
Textags are a special handle (they don't allocate from the general handle stack but via their own private stack) so asyncronous texttags should be fine. |
