| 02-08-2008, 10:58 AM | #1 |
hi people, im trying to implement a modified defend version in my map. im expecting difficulties, so im asking you guys if it can be done without being an advanced jasser. so here it goes - idea: defend ability that does not work in its original way, but reduces the damage of incoming attacks in a certain angle (say: 90°) in front of the defending unit (ie: footman). my approach: 1) modify defend - so it doesnt reduce or deflect any damage 2) if defend is used - add disabled spellbook containing hardened skin ability (ie: reduce damage by 8 points) 3) if defend is switched off - remove spellbook 4) use modified backstab system to detect angle of incoming attacks 5) if attacker is NOT in front of the defending unit - damage defending unit equal to attacker damage (to a maximum of ie: 8 damage) ok, problems start with 5): i cant just trigger 8 damage, because if the attack would deal 5 damage before reduction, the trigger will cause too much damage. so this means if have to use a attack damage system, right? i thought of this one: http://www.wc3campaigns.net/showthread.php?t=98231 but as im using only basic jass functions to remove leaks and such, im not sure if ill be able to implement it well. so basicly i want to know: - if there's an easier way to get the effect i want - some advice how to best approach the detection of attacker damage thx, bsycho |
| 02-08-2008, 12:28 PM | #2 |
Cant you just remake the whole system so it works differently? 1) modify defend - so it doesnt reduce or deflect any damage 2) if defend is used - Add unit to a special group called "yay defend!" 3) defend is switched off - remove the unit from the group 4) when ever a unit from that group is DAMAGED check the modified back stab to see angles 5) if attacker IS in front of defender prevent that damage, then damage the defender for the modified damage (damage - 8 or whatever you wanted). Wouldnt that work much better? |
| 02-08-2008, 12:49 PM | #3 |
if you could explain me how to do that exactly - yes but how do u prevent the damage of a specified source? how do u get the damage value in the first place? so, i still would need the damage detection. |
| 02-08-2008, 01:05 PM | #4 |
sry man i cant show you how now, im sure Pyro or someone will, i gtg go sleep |
| 02-08-2008, 01:49 PM | #5 |
Heh, I have a defend ability coded that works like that, but it requires an altered version of my aBuff system to work. I was going to add damage prevention functionality to my regular release of the system, but it will take me some time to do so. In the meantime, I can supply you with some functions that I use, but not a whole system: JASS:globals private constant integer SURVIVAL_ABILITY = 'A022' //bonus hp ability to allow for prevention of lethal damage endglobals private function DefendAngle takes unit att, unit def returns boolean local real r1 = GetUnitX( att ) local real r2 = GetUnitY( att ) local real r3 = GetUnitX( def ) local real r4 = GetUnitY( def ) local real r5 = Atan2BJ( ( r4 - r2 ), ( r3 - r1 ) ) local real r6 = GetUnitFacing( def ) local real r7 if r5 < 0.0 then set r5 = r5 + 360.0 endif set r7 = r6 - r5 if r7 > 180 then set r7 = r7 - 360 elseif r7 < -180 then set r7 = r7 + 360 endif return (r7>135 or r7<-135) endfunction private function GetUnitArmour takes unit u, unit damager returns real local real armour = 0 if IsUnitInGroup(u, udg_defendingUnits) and DefendAngle(damager, u) then set armour = armour + 8 endif //you can insert other damage reduction effects here return armour endfunction private struct delayedHP unit u real hp endstruct private function DelayedHP takes nothing returns nothing local timerStr t = GetTimerStruct(GetExpiredTimer()) //I use my aBuff system's timers here local delayedHP dhp = delayedHP(t.data) call UnitRemoveAbility(dhp.u, SURVIVAL_ABILITY) call SetWidgetLife(dhp.u, dhp.hp) call dhp.destroy() call t.destroy() endfunction // The following function must be called from a damage detection system private function ArmourSystem takes unit damaged, unit damager, real damage returns real local real armour = GetUnitArmour(damaged, damager) local real life = GetWidgetLife(damaged) local real maxlife = GetUnitState(damaged,UNIT_STATE_MAX_LIFE) local delayedHP dhp local timerStr t //I use my aBuff system's timers here //call BJDebugMsg(GetUnitName(damager)+" deals "+R2S(damage)+" damage. "+GetUnitName(damaged)+"'s armour: "+R2S(armour)) //damage prevention if armour > damage then set armour = damage endif if life-damage+armour>0.405 then //unit should survive, bother about it if maxlife < life+armour then //need a delayed hp restoration call SetWidgetLife(damaged, maxlife) set armour = life-maxlife+armour set dhp = delayedHP.create() set dhp.u=damaged set dhp.hp=maxlife-damage+armour if maxlife-damage <=0.405 then //need a survival ability call UnitAddAbility(damaged, SURVIVAL_ABILITY) endif set t = timerStr.create() set t.data = integer(dhp) call TimerStart(t.t, 0.0, false, function DelayedHP) else //hp may be restored immediately call SetWidgetLife(damaged, life+armour) endif endif return damage endfunction |
| 02-09-2008, 07:52 AM | #6 |
thanks for the help, but as i mentioned, im not the expert jasser so i have my little troubles setting up functions. also i dont want to implement multiple systems only for one spell. currently im using daelin's armor detection system for various reasons. think this will help me to detect the damage as well? it looks quite similar if i check it: JASS:constant function Armor_ID takes nothing returns integer return 'A00C' //rawcode of the auxiliary ability endfunction constant function ADS_Unit takes nothing returns integer return 'h001' //rawcode of ADS unit endfunction //************************************* //Compatibility functions function ADS_AuxiliaryCondition takes nothing returns boolean return GetUnitTypeId(GetEventDamageSource())!=ADS_Unit() endfunction //protected EVENT_UNIT_DAMAGE function TriggerRegisterUnitEventDamaged takes trigger t, unit u returns event call TriggerAddCondition(t, Condition(function ADS_AuxiliaryCondition)) return TriggerRegisterUnitEvent (t, u, EVENT_UNIT_DAMAGED) endfunction //protected damage function function ADS_UnitDamageTarget takes unit whichUnit, unit target, real amount, attacktype attackType, damagetype damageType returns boolean local unit aux = CreateUnit(GetOwningPlayer(whichUnit), ADS_Unit(), GetUnitX(whichUnit), GetUnitY(whichUnit), 0.00) local boolean b = UnitDamageTarget(aux, target, amount, true, false, attackType, damageType, null) call RemoveUnit(aux) set aux = null return b endfunction //************************************* //Auxiliary functions function IsUnitInvulnerable takes unit whichUnit returns boolean local real life local boolean b call UnitAddAbility(whichUnit, 'allz') set life = GetWidgetLife(whichUnit) call ADS_UnitDamageTarget (whichUnit, whichUnit, 0.01, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL) // call UnitDamageTarget(whichUnit, whichUnit, 0.01, false, false, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL, null) if GetWidgetLife(whichUnit)<life then set b = false else set b = true endif call SetWidgetLife(whichUnit, life) call UnitRemoveAbility(whichUnit, 'allz') return b endfunction //************************************* //Armor functions //DETECT UNIT'S ARMOR function GetUnitArmor takes unit whichUnit returns real local real life = GetWidgetLife(whichUnit) local real reduction local integer ID local boolean b if (whichUnit!=null and life>=0.405) then set ID = Armor_ID() set b = IsUnitInvulnerable(whichUnit) call UnitAddAbility(whichUnit, 'allz') call UnitAddAbility(whichUnit, ID) if b==true then call SetUnitInvulnerable(whichUnit, false) endif call ADS_UnitDamageTarget (whichUnit, whichUnit, 16.00, ATTACK_TYPE_CHAOS, DAMAGE_TYPE_NORMAL) if b==true then call SetUnitInvulnerable(whichUnit, true) endif set reduction = (16.00-(life-GetWidgetLife(whichUnit)))/16.00 call UnitRemoveAbility(whichUnit, 'allz') call UnitRemoveAbility(whichUnit, ID) call SetWidgetLife(whichUnit, life) return (50*reduction/(3.00-(3.00*reduction)))-30.00 else return 0.00 endif endfunction //GIVEN INITIAL DAMAGE, DETERMINES HOW MUCH IT WOULD BE REDUCED BY AN AMOUNT OF ARMOR function GetArmorDamage takes real damage, real armor returns real if (armor>=0.00) then return damage*(1-(((armor)*0.06)/(1+0.06*(armor)))) else return damage*(2-Pow(0.94,(-armor))) endif endfunction //GET DAMAGE WITHOUT ARMOR function GetFullDamage takes real damage, real armor returns real if armor>=0.00 then return damage/(1-(((armor)*0.06)/(1.00+0.06*(armor)))) else return damage/(2.00-Pow(0.94,(-armor))) endif endfunction function EvalDamage takes unit whichUnit, real damage, attacktype t, real armor returns real local real life = GetWidgetLife(whichUnit) local real cdam local boolean b = IsUnitInvulnerable(whichUnit) if b==true then call SetUnitInvulnerable(whichUnit, false) endif call ADS_UnitDamageTarget (whichUnit, whichUnit, damage, t, DAMAGE_TYPE_NORMAL) if b==true then call SetUnitInvulnerable(whichUnit, true) endif set cdam = life-GetWidgetLife(whichUnit) call SetWidgetLife(whichUnit, life) return GetFullDamage(cdam, armor) endfunction //DETECT THE ARMOR OF AN UNIT function GetUnitArmorType takes unit whichUnit returns integer local real armor = GetUnitArmor(whichUnit) local real damage call UnitAddAbility(whichUnit, 'allz') set damage = EvalDamage(whichUnit, 16.00,ATTACK_TYPE_MELEE, armor) if (damage<=2.00 and EvalDamage(whichUnit, 16.00, ATTACK_TYPE_CHAOS, armor)>=15.98) then call UnitRemoveAbility(whichUnit, 'allz') return 8 //divine elseif (damage>16.02) then call UnitRemoveAbility(whichUnit, 'allz') return 2 //medium elseif (damage<15.98) then call UnitRemoveAbility(whichUnit, 'allz') return 4 //fortified endif set damage = EvalDamage(whichUnit, 16.00, ATTACK_TYPE_SIEGE, armor) if (damage<15.98) then call UnitRemoveAbility(whichUnit, 'allz') return 6 //hero elseif (damage>16.02) then call UnitRemoveAbility(whichUnit, 'allz') return 7 //unarmored endif if (EvalDamage(whichUnit,16.00,ATTACK_TYPE_PIERCE,armor)>16.02) then call UnitRemoveAbility(whichUnit, 'allz') return 1 //small endif if (EvalDamage(whichUnit,16.00,ATTACK_TYPE_MAGIC,armor)>16.02) then call UnitRemoveAbility(whichUnit, 'allz') return 3 //large else call UnitRemoveAbility(whichUnit, 'allz') return 5 //normal endif endfunction //CONVERT ARMOR TYPE TO STRING constant function A2S takes integer armortype returns string if (armortype==1) then return "small" elseif (armortype==2) then return "medium" elseif (armortype==3) then return "large" elseif (armortype==4) then return "fortified" elseif (armortype==5) then return "normal" elseif (armortype==6) then return "hero" elseif (armortype==7) then return "unarmored" elseif (armortype==8) then return "divine" else return "unknown" endif endfunction //CONVERT STRING TO ARMOR TYPE function S2A takes string s returns integer set s = StringCase(s,false) if (s=="small") then return 1 elseif (s=="medium") then return 2 elseif (s=="large") then return 3 elseif (s=="fortified") then return 4 elseif (s=="normal") then return 5 elseif (s=="hero") then return 6 elseif (s=="unarmored") then return 7 elseif (s=="divine") then return 8 else return 0 endif endfunction |
| 02-09-2008, 10:40 PM | #7 |
I don't see how is Armor Detection System is going to help you. Why don't you show what code you do have so we can better help you. Additionally, you may find this useful: Detecting a Backstab |
