• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

[JASS] Ability based on # of units nearby

Status
Not open for further replies.
Level 3
Joined
Nov 12, 2006
Messages
35
OK, so Im creating a map with JASS for the first time. Im very inexperienced. I want an outline for how to code an ability type. The generic type is that a unit gets a numerical bonus to a stat based on the number of friendly units (of the same type) within a certain range of the unit.

For Example; The militia unit gets +1 damage for every other friendly militia unit within 300 range of it. 5 militia units are all within 300 range of one another. Each militia unit would gain +4 to its damage.

Any idea on how to code this in JASS. Also, would it take up to much memory? I mean if there are 40 militia units, would It severely slow down the computer?

Thanks for any help.
 
Level 9
Joined
Apr 5, 2008
Messages
529
This should work.

JASS:
function Trig_Peasant_Attack_Conditions takes nothing returns boolean
  return GetUnitTypeId(GetAttacker()) == 'Hpea'
endfunction

function PeasantAttack_Filter takes nothing returns boolean
  return IsUnitAlly(GetAttacker(), GetFilterUnit())
endfunction

function Trig_Peasant_Attack_Actions takes nothing returns nothing
  local group group = CreateGroup()
  local boolexpr Boolexpr = Condition(function PeasantAttack_Filter)
  local real X = GetUnitX(GetAttacker())
  local real Y = GetUnitY(GetAttacker())
  local integer Count
  
  call GroupEnumUnitsInRange(Group, X, Y, 300, Boolexpr)
  set Count = CountUnitsInGroup(Group)
  call UnitDamageTarget(GetAttacker(), GetTriggerUnit(), count, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_LIGHT_CHOP) 

  call DestroyGroup(Group)
  set Group = null
  call DestroyBoolExpr(Boolexpr)
  set Boolexpr = null
endfunction

//===========================================================================
function InitTrig_Peasant_Attack takes nothing returns nothing
    set gg_trg_Peasant_Attack = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Peasant_Attack, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_Peasant_Attack, Condition( function Trig_Peasant_Attack_Conditions ) )
    call TriggerAddAction( gg_trg_Peasant_Attack, function Trig_Peasant_Attack_Actions )
endfunction
 
Last edited:
Level 11
Joined
Feb 18, 2004
Messages
394
This should work.

JASS:
function Trig_Peasant_Attack_Conditions takes nothing returns boolean
  return GetUnitTypeId(GetAttacker()) == 'Hpea'
endfunction

function PeasantAttack_Filter takes nothing returns boolean
  return IsUnitAlly(GetAttacker(), GetFilterUnit())
endfunction

function Trig_Peasant_Attack_Actions takes nothing returns nothing
  local group group = CreateGroup()
  local boolexpr Boolexpr = Condition(function PeasantAttack_Filter)
  local real X = GetUnitX(GetAttacker())
  local real Y = GetUnitY(GetAttacker())
  local integer Count
  
  call GroupEnumUnitsInRange(Group, X, Y, 300, Boolexpr)
  set Count = CountUnitsInGroup(Group)
  call UnitDamageTarget(GetAttacker(), GetTriggerUnit(), count, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_LIGHT_CHOP) 

  call DestroyGroup(Group)
  set Group = null
  call DestroyBoolExpr(Boolexpr)
  set Boolexpr = null
endfunction

//===========================================================================
function InitTrig_Peasant_Attack takes nothing returns nothing
    set gg_trg_Peasant_Attack = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Peasant_Attack, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_Peasant_Attack, Condition( function Trig_Peasant_Attack_Conditions ) )
    call TriggerAddAction( gg_trg_Peasant_Attack, function Trig_Peasant_Attack_Actions )
endfunction

you don't have to destroy boolexprs. For the same input, Condition() will produce the same output. You also use some unneeded locals, and a few case errors. Fixing all i can see:
JASS:
function Trig_Peasant_Attack_Conditions takes nothing returns boolean
  return GetUnitTypeId(GetAttacker()) == 'Hpea'
endfunction

function PeasantAttack_Filter takes nothing returns boolean
  return IsUnitAlly(GetAttacker(), GetFilterUnit())
endfunction

function Trig_Peasant_Attack_Actions takes nothing returns nothing
  local group Group = CreateGroup()
  
  call GroupEnumUnitsInRange(Group, GetUnitX(GetAttacker()), GetUnitY(GetAttacker()), 300, Condition(function PeasantAttack_Filter))
  call UnitDamageTarget(GetAttacker(), GetTriggerUnit(), CountUnitsInGroup(Group), true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_METAL_LIGHT_CHOP) 

  call DestroyGroup(Group)
  set Group = null
endfunction

//===========================================================================
function InitTrig_Peasant_Attack takes nothing returns nothing
    set gg_trg_Peasant_Attack = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Peasant_Attack, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_Peasant_Attack, Condition( function Trig_Peasant_Attack_Conditions ) )
    call TriggerAddAction( gg_trg_Peasant_Attack, function Trig_Peasant_Attack_Actions )
endfunction

Anyway, that won't work out so well anyway.

the "EVENT_PLAYER_UNIT_ATTACKED" event happens when a unit begins attacking, not when a unit finishes attacking. Thus, this can deal damage when the unit doesn't even have to finish an attack.

A better way to go about this would be using a periodic timer using GroupEnumUnitsInRange(), adjusting a damage bonus for how many allys are nearby. You can add a damage bonus with the Item Damage Bonus ability. Just add an ability based on it to add a damage bonus, and remove the ability to remove the bonus.
 
Level 3
Joined
Nov 12, 2006
Messages
35
Thanks so much guys. So your saying I should have a timer, say every second, and a trigger that adjusts the damage bonus provided by an ability based upon the Item Damage Bonus ability?
 
Status
Not open for further replies.
Top