• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

Looking for Threat system

Status
Not open for further replies.
Level 2
Joined
Dec 12, 2017
Messages
26
Hello everyone, third post.
As I said in other posts, some time ago I am working on a RPG map for 1 player where he controls a warrior, an archer, a rogue and a priest, what I am looking for is a threat system like Zwiebelchen's Threat System 2.7 but due to my null knowledge of jass I do not know how to implement it, but i think that system is perfect for me.

  • What I'm looking for is for the creeps to fight in groups, that is, if the player attacks a creep of a group of three, for example, that all the creeps of that group enter combat, and then, for example if the player group of heroes dies or retires from battle (moves away), the creeps return to the position where they were initially, as "resetting" and during the return way they are invulnerable and when they finally reach their initial position, they recover all their life and mana and become vulnerable again, just like the World of Warcraft threat system.
Keep in mind that I am already using the custom value of hostile neutral units for the next respawn system, which I do not remember who the author is, but I quote the triggers below. Thank you for your attention and I hope you can help me.

  • Creep Revival System Initialization Copiar Copiar 2
    • Acontecimientos
      • Map initialization
    • Condiciones
    • Acciones
      • Set Respawn_Time = 90.00
      • Grupo de unidad - Pick every unit in (Units in (Playable map area) owned by Neutral hostil) and do (Actions)
        • Bucle: Acciones
          • Set Temp_Integer = (Temp_Integer + 1)
          • Unidad - Set the custom value of (Picked unit) to Temp_Integer
          • Set Creep_Point[Temp_Integer] = (Position of (Picked unit))
          • Set Creep_Face[Temp_Integer] = (Facing of (Picked unit))
          • Set Creep_Range[Temp_Integer] = (Current acquisition range of (Triggering unit))
  • Creep Revival System Initialization Copiar Copiar Copiar
    • Acontecimientos
      • Unidad - A unit Muere
    • Condiciones
      • And - All (Conditions) are true
        • Condiciones
          • (Custom value of (Triggering unit)) Mayor que 0
          • (Owner of (Triggering unit)) Igual a Neutral hostil
    • Acciones
      • Custom script: local integer i = GetUnitTypeId(GetTriggerUnit())
      • Custom script: local integer ii = GetUnitUserData(GetTriggerUnit())
      • Wait Respawn_Time game-time seconds
      • Custom script: call SetUnitUserData(CreateUnit(Player(PLAYER_NEUTRAL_AGGRESSIVE),i,GetLocationX(udg_Creep_Point[ii]),GetLocationY(udg_Creep_Point[ii]),udg_Creep_Face[ii]),ii)
      • Custom script: call SetUnitAcquireRangeBJ(GetTriggerUnit(),udg_Creep_Range[udg_Temp_Integer])
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Using your custom value for something like that is not really recommended, since you can achieve that same functionality without using up the custom value. The problem is that many GUI systems use CV for some integral part (usually unit indexing), so you might end up with 2 systems needing to use it for something. Most JASS systems will not have this limitation, though it is possible. Instead what I suggest you do is use Zwiebelchen's and fix your creep reviver.

To do that add the following to the first trigger:
  • Set Respawn_Time = 90.00
  • Set Temp_Integer = 0
  • -------- Inside the unit group pick--------
  • Set Creep_Type[Temp_Integer] = (Unit type of (Picked Unit))
  • Set Creep_Creep[Temp_Integer] = (Picked Unit)
  • Unit Group - Add (Picked Unit) to (Respawn_Group) //new unit group to hold creeps
  • -------- outside of group pick --------
  • Set Respawn_Number = Temp_Integer //Now you know how many creeps there are
Then create a new integer variable (I called mine "NEW_INT") and in your revive do this:
  • -------- Replace all conditions with this --------
    • (Triggering Unit) is in Respawn_Group equal to true
  • -------- Replace all actions with this --------
  • Custom script: local integer udg_NEW_INT //you will have to replace the variable name here with whatever you call yours, but keep the udg_; this makes a fake local variable to store the data during the wait
  • For each (integer NEW_INT) from 1 to Respawn_Number do (actions)
    • Loop - Actions
      • If (Conditions) then (Actions) else (Actions)
        • If - Conditions
          • Creep_Creep[NEW_INT] equal to (triggering unit)
        • Then - Actions
          • Unit Group - Remove Creep_Creep[NEW_INT] from Respawn_Group
          • Custom script: exitwhen true //now you know which creep died; NEW_INT tells us the index
        • Else - Actions
  • Wait Respawn_Time game-time seconds
  • Unit - Create 1 Creep_Type[NEW_INT] for Neutral Aggressive at Creep_Point[NEW_INT] facing Creep_Face[NEW_INT]
  • Set Creep_Creep[NEW_INT] = (last created unit)
  • Unit - Set acquisition range for Creep_Creep[NEW_INT] to Creep_Range[NEW_INT]
  • Unit Group - Add Creep_Creep[NEW_INT] to Respawn_Group
 
Level 2
Joined
Dec 12, 2017
Messages
26
Using your custom value for something like that is not really recommended, since you can achieve that same functionality without using up the custom value. The problem is that many GUI systems use CV for some integral part (usually unit indexing), so you might end up with 2 systems needing to use it for something. Most JASS systems will not have this limitation, though it is possible. Instead what I suggest you do is use Zwiebelchen's and fix your creep reviver.

That's great man, thanks for fixing the respawn, I'm going to implement that and I'll tell you if it works.
About the system of Zwiebelchen's, says that it requires vJass preprocessor, what is that? Do you need a modified version of the WE or can I implement it with the standard version? XD sorry for my ignorance and thanks for your help

EDIT: Looking carefully the system of Zwiebelchen's, I think it is very complicated for me because I do not understand jass and that system requires implementing lines of code to make it work, I am satisfied only with the part of hostile neutral units attacking in group and when they are returning to their initial position if the player retired from battle or die, make their invulnerable, recover life and mana on the way back and when reach initial position be vulnerable again. I think it can be done in a simpler way, but I do not know how.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,013
A vJASS preprocessor is the thing that turns the vJASS into regular JASS, and you get that in WEX or JNGP. So you need to download WEX, as this system is really not that hard to set up and use as you want it to function. When you find a resource like this, please just read the documentation supplied in the map. Here's what comes with his system:
JASS:
/------------------------------------------------------------------------------------------------------//
//  ZTS - ZWIEBELCHEN'S THREAT SYSTEM        v. 2.6                                                     //
//------------------------------------------------------------------------------------------------------//         
//------------------------------------------------------------------------------------------------------//
//                                                                                                      //
//  Requires: vJass Pre-Processor                                                                       //
//                                                                                                      //
//  Special thanks to TEC-Ghost, who inspired me on creating this system.                               //
//------------------------------------------------------------------------------------------------------//
//                                              MANUAL                                                  //
//------------------------------------------------------------------------------------------------------//
// 1.   How to Install:
//
//      - Create a trigger called "ZTS"
//      - Convert it to custom Text
//      - Replace everything inside with this code
//
//
// 2.   How to set it up:
//
//  2.1 Constants
//
//      There are a bunch of global constants below this manual, you can edit to your liking.
//      I commented everything you need to know about those constants right beside them. If you need additional information,
//      please tell me, so I can improve this manual. However, I think most of it should be pretty clear.
//
//  2.2. Gameplay Constants
//
//      It is recommended to edit certain Gameplay Constants entries, to use the full potential of
//      the system.
//      The most important entries are: (with selected "Show Raw-Data")
//      CallForHelp                 --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
//                                      You don't have to do it if your threat-system controlled units are neutral hostile
//      CreepCallForHelp            --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
//      GuardDistance               --> Set this to something higher than ReturnRange (see below)
//      MaxGuardDistance            --> Set this to something higher than ReturnRange (see below)
//      GuardReturnTime             --> Set this to something very high, so that the standard AI doesn't interfere (i.e. 60 seconds)       
//
//  2.3. Damage Detection
//
//      Of course, a threat system is pretty useless without a trigger, that adds threat depending on
//      the damage dealt by a player unit.
//      I recommend using a damage detection script like IDDS:
//      (http://www.wc3c.net/showthread.php?t=100618)
//      Check up the demo map for a very simple (but leaking) damage detection trigger
//      The only function you actually need then is:
//      call ModifyThreat(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage(), true)
//      The function does all required checks on its own. There is no need to run something else.
//
// 3. How to use it:
//
//  3.1. Core functions
//
//      call ZTS_AddThreatUnit(unit npc, boolean includeCombatCamps) returns nothing:
//
//          This function registers the unit as an AI-controlled unit.
//          ThreatUnits will automaticly attack the highest-in-threat attacker.
//          When adding a ThreatUnit, its current position gets saved and be considered camp-position.
//          It will always return to this position if pulled to far or on victory.
//          Nearby units will be considered in the same camp group. Camp members will always retreat and attack together.
//          If includeCombatCamps is true, the unit will be added to already fighting camps. If it is false, the unit will
//          create its own camp group, if it can't find any non-fighting units nearby.
//          This should be false in most cases, but it can be useful when you have bosses that summon units infight, so that
//          the summons will be added to the bossfight correctly instead of getting their own seperate group.
//
//      call ZTS_AddPlayerUnit(unit pu) returns nothing:
//
//          Units add by this way will generate threat on ThreatUnits.
//          If the unit is not registered as a PlayerUnit, it will not be attacked by ThreatUnits.
//
//      call ZTS_RemoveThreatUnit(unit npc) returns nothing:
//
//          Removes a ThreatUnit from the system. The unit will no longer be controlled by the threat system.
//          Also, the threat list for that unit will be cleared.
//          Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
//      call ZTS_RemovePlayerUnit(unit pu) returns nothing:
//
//          Removes a player unit from the system. The unit will no longer generate threat on ThreatUnits.
//          The unit will also be instantly removed from all threat lists.
//          If the unit was the last unit in combat with the same hostile camp, all units
//          of that camp group will immediately return to their camp positions.
//          You can use this, followed by AddPlayerUnit to that unit out of combat and reset all threat.
//          Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
//      call ZTS_ModifyThreat(unit pu, unit npc, real amount, boolean add) returns nothing:
//
//          Adds, sets or substracts threat from npc's threat list caused by pu.
//          Set 'add' to true to add or substract amount from the current value.
//          Set 'add' to false to set the new threat value to amount.
//          To reduce threat, use negative amount values with add == true.
//          Remember: If a unit has 0 threat, it is still considered in-combat -
//          this also means, that adding "0" to the units threat causes them to attack!
//
//      call ZTS_ApplyHealThreat(unit pu, unit ally, real amount, boolean add, boolean divide) returns nothing:
//
//          Adds Healing Threat to all units, that have ally on threat-list
//          This can be abused to apply global threat to a unit by passing the same unit to p and ally.
//          Parameter divide = true means that the amount is split by the number of units attacking the target;
//          for example if 3 units are currently attacking the targeted ally, it adds amount/3 threat from pu to all of them.
//          Parameter divide = false means that every attacking unit gets 'amount' of threat applied.
//          use add = false to set the amount of threat to 'amount', instead of increasing/decreasing it
//          negative values are allowed in combination with 'add' to reduce threat.
//          You can also use this with add = false and amount = 0 with pu = ally to set total threat generated back to zero for this unit.
//
//
//  3.2. Getter functions
//
//      call ZTS_GetCombatState(unit U) returns boolean:
//
//          Returns the combat state of a player or npc unit.
//          Returns true, if the unit is registered and in combat.
//          Returns false, if the unit is not registered or out of combat.
//
//      call ZTS_GetCombatTime(unit NPC) returns boolean:
//
//          Returns the incombat time of the npc.
//          Does not work for player units.
//          Returns "0" if the unit is not in combat or currently returning to camp position.
//
//      call ZTS_GetThreatUnitPosition(unit NPC, unit PU) returns integer:
//
//          Returns the position of unit PU in unit NPC's threat list
//          Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
//      call ZTS_GetThreatUnitAmount(unit NPC, unit PU) returns real:
//
//          Returns the amount of threat unit PU has in unit NPC's threat list
//          Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
//      call ZTS_GetThreatSlotUnit(unit NPC, integer position) returns unit:
//
//          Returns the unit in threat-slot position
//          Returns null if the NPC does not feature a threat list, the number is too large
//          or in case of invalid input data
//
//      call ZTS_GetThreatSlotAmount(unit NPC, integer position) returns real:
//
//          Returns the threat amount of the threat-slot position
//          Returns "0" if the NPC does not feature a threat list, the number is too large
//          or in case of invalid input data
//
//      call ZTS_GetAttackers(unit U) returns group:
//
//          If used on a ThreatUnit, this returns a group of all units in threat list;
//          if used on a PlayerUnit, this returns a group of all units aggroed.
//          Returns an empty group, in case of invalid input data or empty lists.
//
// 
//  3.3. Advanced User features
//
//      call ZTS_IsEvent() returns boolean
//
//          When using "A unit is issued an order without target" or "A unit is issued a target order" events,
//          this function returns true when the order was issued by the threat system.
//          You can use this to setup your own spell-AI for units.
//          Let's say you want the unit to cast Summon Water Elemental whenever the cooldown is ready:
//          Just use the mentioned events and add:
//              Custom script:   if not ZTS_IsEvent() then
//              Custom script:   return
//              Custom script:   endif
//          at the beginning of you trigger's actions and you're done.
//          You can now issue the order to the triggering unit:
//              Unit - Order (Triggering unit) to Human Archmage - Summon Water Elemental
//          In combination with some of the Getter functions, you can trigger nice spell AI like this.
//          NOTE: ZTS_IsEvent will only return true once(!) for every fired event, so if you need it again inside that trigger,
//                make sure to save it to a variable.
//
//------------------------------------------------------------------------------------------------------//

library ZTS initializer InitThreatSystem

globals   
    private constant real UpdateIntervall = 0.5 //The intervall for issueing orders and performing AttackRange check. recommended value: 0.5
    private constant real HelpRange = 400 //The range between units considered being in the same camp. If a unit of the same camp gets attacked, all others will help.
                                          //Set CallForHelp to something lower in Gameplay Constants.
    private constant real OrderReturnRange = 4000 //The range the unit's target can be away from the original camping position, before being ordered to return.
    private constant real ReturnRange = 1500 //The range the unit can move away from the original camping position, before being ordered to return.
    private constant real TimeToPort = 10 //This timer expires once a unit tries to return to its camping position.
                                          //If it reaches 0 before reaching the camp position, the unit will be teleported immediately.
    private constant boolean HealUnitsOnReturn = true //If this is true, returning units will be healed to 100% health.
   
   
//      Do not edit below here!
//------------------------------------------------------------------------------------------------------//
So to make it work in your map the entirety of what you have to do is:
  1. Import a damage detect system into your map (there are a few here that run in GUI like GDD)
  2. Configure the imported DDS as its documentation outlines you should do
  3. Copy over the ZTS trigger into your map, thus importing his threat system
  4. Configure the little bit of ZTS you have to (maybe you don't change it all, idk)
  5. Figure out how to use your DDS to run something (probably a trigger with no events) when a unit takes damage, and copy over the custom script line from the "DamageDetect" trigger in the ZTS map. This is what tells the game to add threat when units take damage. The DDS you pick might specify variables to use to get targeted units/damage or might say to use the GetTriggerUnit() syntax that's already there. You should be able to figure this out from example code in the DDS you pick, but post if you're confused.
  6. Make your own trigger like his "Init" trigger that sets up units into the ZTS system. You don't have to use the trigger add action loop, just pick every unit you want to behave like it has threat (all creeps) and do that custom script call. Do the same for player units (things that should generate threat). Again ask if confused.
 
Level 2
Joined
Dec 12, 2017
Messages
26
Using your custom value for something like that is not really recommended, since you can achieve that same functionality without using up the custom value. The problem is that many GUI systems use CV for some integral part (usually unit indexing), so you might end up with 2 systems needing to use it for something. Most JASS systems will not have this limitation, though it is possible. Instead what I suggest you do is use Zwiebelchen's and fix your creep reviver.

To do that add the following to the first trigger:
  • Set Respawn_Time = 90.00
  • Set Temp_Integer = 0
  • -------- Inside the unit group pick--------
  • Set Creep_Type[Temp_Integer] = (Unit type of (Picked Unit))
  • Set Creep_Creep[Temp_Integer] = (Picked Unit)
  • Unit Group - Add (Picked Unit) to (Respawn_Group) //new unit group to hold creeps
  • -------- outside of group pick --------
  • Set Respawn_Number = Temp_Integer //Now you know how many creeps there are
Then create a new integer variable (I called mine "NEW_INT") and in your revive do this:
  • -------- Replace all conditions with this --------
    • (Triggering Unit) is in Respawn_Group equal to true
  • -------- Replace all actions with this --------
  • Custom script: local integer udg_NEW_INT //you will have to replace the variable name here with whatever you call yours, but keep the udg_; this makes a fake local variable to store the data during the wait
  • For each (integer NEW_INT) from 1 to Respawn_Number do (actions)
    • Loop - Actions
      • If (Conditions) then (Actions) else (Actions)
        • If - Conditions
          • Creep_Creep[NEW_INT] equal to (triggering unit)
        • Then - Actions
          • Unit Group - Remove Creep_Creep[NEW_INT] from Respawn_Group
          • Custom script: exitwhen true //now you know which creep died; NEW_INT tells us the index
        • Else - Actions
  • Wait Respawn_Time game-time seconds
  • Unit - Create 1 Creep_Type[NEW_INT] for Neutral Aggressive at Creep_Point[NEW_INT] facing Creep_Face[NEW_INT]
  • Set Creep_Creep[NEW_INT] = (last created unit)
  • Unit - Set acquisition range for Creep_Creep[NEW_INT] to Creep_Range[NEW_INT]
  • Unit Group - Add Creep_Creep[NEW_INT] to Respawn_Group

Understood, not use the CV for something like this, I will try to implement the Zwiebelchen's System, but first I got a problem with the trigger you created, edit everything as you said but the creeps didn't respawn at all, I quote the trigger as it is, can you find the problem? Thank you. PD: I create the variable NEW_UNIT instead of NEW_INT.
Thanks for your attention

  • Creep Revival System Initialization Copiar Copiar 2
    • Acontecimientos
      • Map initialization
    • Condiciones
    • Acciones
      • Set Respawn_Time = 5.00
      • Set Temp_Integer = 0
      • Grupo de unidad - Pick every unit in (Units in (Playable map area) owned by Neutral hostil) and do (Actions)
        • Bucle: Acciones
          • Set Temp_Integer = (Temp_Integer + 1)
          • Set Creep_Point[Temp_Integer] = (Position of (Picked unit))
          • Set Creep_Face[Temp_Integer] = (Facing of (Picked unit))
          • Set Creep_Range[Temp_Integer] = (Default acquisition range of (Picked unit))
          • Set Creep_Type[Temp_Integer] = (Unit-type of (Picked unit))
          • Set Creep_Creep[Temp_Integer] = (Picked unit)
          • Grupo de unidad - Add (Picked unit) to Respawn_Group
      • Set Respawn_Number = Temp_Integer
  • Creep Revival System Initialization Copiar Copiar Copiar
    • Acontecimientos
      • Unidad - A unit Muere
    • Condiciones
      • ((Triggering unit) is in Respawn_Group) Igual a True
    • Acciones
      • Custom script: local integer udg_NEW_UNIT
      • For each (Integer NEW_UNIT) from 1 to Respawn_Number, do (Actions)
        • Bucle: Acciones
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • Si: Condiciones
              • Creep_Creep[NEW_UNIT] Igual a (Triggering unit)
            • Entonces: Acciones
              • Grupo de unidad - Remove Creep_Creep[NEW_UNIT] from Respawn_Group
              • Custom script: exitwhen true
            • Otros: Acciones
      • Wait Respawn_Time game-time seconds
      • Unidad - Create 1 Creep_Type[NEW_UNIT] for Neutral hostil at Creep_Point[NEW_UNIT] facing Creep_Face[NEW_UNIT] degrees
      • Set Creep_Creep[NEW_UNIT] = (Last created unit)
      • Unidad - Set Creep_Creep[NEW_UNIT] acquisition range to Creep_Range[NEW_UNIT]
      • Grupo de unidad - Add Creep_Creep[NEW_UNIT] to Respawn_Group
 
Level 2
Joined
Dec 12, 2017
Messages
26
A vJASS preprocessor is the thing that turns the vJASS into regular JASS, and you get that in WEX or JNGP. So you need to download WEX, as this system is really not that hard to set up and use as you want it to function. When you find a resource like this, please just read the documentation supplied in the map. Here's what comes with his system:
JASS:
/------------------------------------------------------------------------------------------------------//
//  ZTS - ZWIEBELCHEN'S THREAT SYSTEM        v. 2.6                                                     //
//------------------------------------------------------------------------------------------------------//        
//------------------------------------------------------------------------------------------------------//
//                                                                                                      //
//  Requires: vJass Pre-Processor                                                                       //
//                                                                                                      //
//  Special thanks to TEC-Ghost, who inspired me on creating this system.                               //
//------------------------------------------------------------------------------------------------------//
//                                              MANUAL                                                  //
//------------------------------------------------------------------------------------------------------//
// 1.   How to Install:
//
//      - Create a trigger called "ZTS"
//      - Convert it to custom Text
//      - Replace everything inside with this code
//
//
// 2.   How to set it up:
//
//  2.1 Constants
//
//      There are a bunch of global constants below this manual, you can edit to your liking.
//      I commented everything you need to know about those constants right beside them. If you need additional information,
//      please tell me, so I can improve this manual. However, I think most of it should be pretty clear.
//
//  2.2. Gameplay Constants
//
//      It is recommended to edit certain Gameplay Constants entries, to use the full potential of
//      the system.
//      The most important entries are: (with selected "Show Raw-Data")
//      CallForHelp                 --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
//                                      You don't have to do it if your threat-system controlled units are neutral hostile
//      CreepCallForHelp            --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
//      GuardDistance               --> Set this to something higher than ReturnRange (see below)
//      MaxGuardDistance            --> Set this to something higher than ReturnRange (see below)
//      GuardReturnTime             --> Set this to something very high, so that the standard AI doesn't interfere (i.e. 60 seconds)      
//
//  2.3. Damage Detection
//
//      Of course, a threat system is pretty useless without a trigger, that adds threat depending on
//      the damage dealt by a player unit.
//      I recommend using a damage detection script like IDDS:
//      (http://www.wc3c.net/showthread.php?t=100618)
//      Check up the demo map for a very simple (but leaking) damage detection trigger
//      The only function you actually need then is:
//      call ModifyThreat(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage(), true)
//      The function does all required checks on its own. There is no need to run something else.
//
// 3. How to use it:
//
//  3.1. Core functions
//
//      call ZTS_AddThreatUnit(unit npc, boolean includeCombatCamps) returns nothing:
//
//          This function registers the unit as an AI-controlled unit.
//          ThreatUnits will automaticly attack the highest-in-threat attacker.
//          When adding a ThreatUnit, its current position gets saved and be considered camp-position.
//          It will always return to this position if pulled to far or on victory.
//          Nearby units will be considered in the same camp group. Camp members will always retreat and attack together.
//          If includeCombatCamps is true, the unit will be added to already fighting camps. If it is false, the unit will
//          create its own camp group, if it can't find any non-fighting units nearby.
//          This should be false in most cases, but it can be useful when you have bosses that summon units infight, so that
//          the summons will be added to the bossfight correctly instead of getting their own seperate group.
//
//      call ZTS_AddPlayerUnit(unit pu) returns nothing:
//
//          Units add by this way will generate threat on ThreatUnits.
//          If the unit is not registered as a PlayerUnit, it will not be attacked by ThreatUnits.
//
//      call ZTS_RemoveThreatUnit(unit npc) returns nothing:
//
//          Removes a ThreatUnit from the system. The unit will no longer be controlled by the threat system.
//          Also, the threat list for that unit will be cleared.
//          Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
//      call ZTS_RemovePlayerUnit(unit pu) returns nothing:
//
//          Removes a player unit from the system. The unit will no longer generate threat on ThreatUnits.
//          The unit will also be instantly removed from all threat lists.
//          If the unit was the last unit in combat with the same hostile camp, all units
//          of that camp group will immediately return to their camp positions.
//          You can use this, followed by AddPlayerUnit to that unit out of combat and reset all threat.
//          Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
//      call ZTS_ModifyThreat(unit pu, unit npc, real amount, boolean add) returns nothing:
//
//          Adds, sets or substracts threat from npc's threat list caused by pu.
//          Set 'add' to true to add or substract amount from the current value.
//          Set 'add' to false to set the new threat value to amount.
//          To reduce threat, use negative amount values with add == true.
//          Remember: If a unit has 0 threat, it is still considered in-combat -
//          this also means, that adding "0" to the units threat causes them to attack!
//
//      call ZTS_ApplyHealThreat(unit pu, unit ally, real amount, boolean add, boolean divide) returns nothing:
//
//          Adds Healing Threat to all units, that have ally on threat-list
//          This can be abused to apply global threat to a unit by passing the same unit to p and ally.
//          Parameter divide = true means that the amount is split by the number of units attacking the target;
//          for example if 3 units are currently attacking the targeted ally, it adds amount/3 threat from pu to all of them.
//          Parameter divide = false means that every attacking unit gets 'amount' of threat applied.
//          use add = false to set the amount of threat to 'amount', instead of increasing/decreasing it
//          negative values are allowed in combination with 'add' to reduce threat.
//          You can also use this with add = false and amount = 0 with pu = ally to set total threat generated back to zero for this unit.
//
//
//  3.2. Getter functions
//
//      call ZTS_GetCombatState(unit U) returns boolean:
//
//          Returns the combat state of a player or npc unit.
//          Returns true, if the unit is registered and in combat.
//          Returns false, if the unit is not registered or out of combat.
//
//      call ZTS_GetCombatTime(unit NPC) returns boolean:
//
//          Returns the incombat time of the npc.
//          Does not work for player units.
//          Returns "0" if the unit is not in combat or currently returning to camp position.
//
//      call ZTS_GetThreatUnitPosition(unit NPC, unit PU) returns integer:
//
//          Returns the position of unit PU in unit NPC's threat list
//          Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
//      call ZTS_GetThreatUnitAmount(unit NPC, unit PU) returns real:
//
//          Returns the amount of threat unit PU has in unit NPC's threat list
//          Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
//      call ZTS_GetThreatSlotUnit(unit NPC, integer position) returns unit:
//
//          Returns the unit in threat-slot position
//          Returns null if the NPC does not feature a threat list, the number is too large
//          or in case of invalid input data
//
//      call ZTS_GetThreatSlotAmount(unit NPC, integer position) returns real:
//
//          Returns the threat amount of the threat-slot position
//          Returns "0" if the NPC does not feature a threat list, the number is too large
//          or in case of invalid input data
//
//      call ZTS_GetAttackers(unit U) returns group:
//
//          If used on a ThreatUnit, this returns a group of all units in threat list;
//          if used on a PlayerUnit, this returns a group of all units aggroed.
//          Returns an empty group, in case of invalid input data or empty lists.
//
//
//  3.3. Advanced User features
//
//      call ZTS_IsEvent() returns boolean
//
//          When using "A unit is issued an order without target" or "A unit is issued a target order" events,
//          this function returns true when the order was issued by the threat system.
//          You can use this to setup your own spell-AI for units.
//          Let's say you want the unit to cast Summon Water Elemental whenever the cooldown is ready:
//          Just use the mentioned events and add:
//              Custom script:   if not ZTS_IsEvent() then
//              Custom script:   return
//              Custom script:   endif
//          at the beginning of you trigger's actions and you're done.
//          You can now issue the order to the triggering unit:
//              Unit - Order (Triggering unit) to Human Archmage - Summon Water Elemental
//          In combination with some of the Getter functions, you can trigger nice spell AI like this.
//          NOTE: ZTS_IsEvent will only return true once(!) for every fired event, so if you need it again inside that trigger,
//                make sure to save it to a variable.
//
//------------------------------------------------------------------------------------------------------//

library ZTS initializer InitThreatSystem

globals  
    private constant real UpdateIntervall = 0.5 //The intervall for issueing orders and performing AttackRange check. recommended value: 0.5
    private constant real HelpRange = 400 //The range between units considered being in the same camp. If a unit of the same camp gets attacked, all others will help.
                                          //Set CallForHelp to something lower in Gameplay Constants.
    private constant real OrderReturnRange = 4000 //The range the unit's target can be away from the original camping position, before being ordered to return.
    private constant real ReturnRange = 1500 //The range the unit can move away from the original camping position, before being ordered to return.
    private constant real TimeToPort = 10 //This timer expires once a unit tries to return to its camping position.
                                          //If it reaches 0 before reaching the camp position, the unit will be teleported immediately.
    private constant boolean HealUnitsOnReturn = true //If this is true, returning units will be healed to 100% health.
  
  
//      Do not edit below here!
//------------------------------------------------------------------------------------------------------//
So to make it work in your map the entirety of what you have to do is:
  1. Import a damage detect system into your map (there are a few here that run in GUI like GDD)
  2. Configure the imported DDS as its documentation outlines you should do
  3. Copy over the ZTS trigger into your map, thus importing his threat system
  4. Configure the little bit of ZTS you have to (maybe you don't change it all, idk)
  5. Figure out how to use your DDS to run something (probably a trigger with no events) when a unit takes damage, and copy over the custom script line from the "DamageDetect" trigger in the ZTS map. This is what tells the game to add threat when units take damage. The DDS you pick might specify variables to use to get targeted units/damage or might say to use the GetTriggerUnit() syntax that's already there. You should be able to figure this out from example code in the DDS you pick, but post if you're confused.
  6. Make your own trigger like his "Init" trigger that sets up units into the ZTS system. You don't have to use the trigger add action loop, just pick every unit you want to behave like it has threat (all creeps) and do that custom script call. Do the same for player units (things that should generate threat). Again ask if confused.

Great explanation, thank you very much
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Try putting a debug message in the "Then - Actions" that will display the value of the NEW_UNIT variable when it finds a match with a creep.
  • Game - Display to (All Players) the text ("NEW_UNIT equal to "+I2S(NEW_UNIT))
My best guess is that the condition in the second trigger is never true because your units are decaying off the map super quickly and thus aren't finding a match when it searches through the stored Creeps. Honestly the better way to do this is to make a simple hashtable object to store the units. Something like:

  • -------- on map init --------
  • Hashtable - Create new hashtable
  • Set YOUR_HASH = (last created hashtable)
  • -------- --------
  • Grupo de unidad - Pick every unit in (Units in (Playable map area) owned by Neutral hostil) and do (Actions)
    • Bucle: Acciones
      • Set Temp_Integer = (Temp_Integer + 1)
      • Set Creep_Point[Temp_Integer] = (Position of (Picked unit))
      • Set Creep_Face[Temp_Integer] = (Facing of (Picked unit))
      • Set Creep_Range[Temp_Integer] = (Default acquisition range of (Picked unit))
      • Set Creep_Type[Temp_Integer] = (Unit-type of (Picked unit))
      • Set Creep_Creep[Temp_Integer] = (Picked unit)
      • Grupo de unidad - Add (Picked unit) to Respawn_Group
      • -------- vvvvv --------
      • Hashtable - Save Temp_Integer as 0 of (Key (Picked unit)) in YOUR_HASH
  • Set Respawn_Number = Temp_Integer
  • Creep Revival System Initialization Copiar Copiar Copiar
    • Acontecimientos
      • Unidad - A unit Muere
    • Condiciones
      • ((Triggering unit) is in Respawn_Group) Igual a True
    • Acciones
      • Custom script: local integer udg_NEW_UNIT
      • Set NEW_UNIT = (Load 0 of (Key (Triggering unit)) from YOUR_HASH)
      • Hashtable - Clear all child hashtables of child (Key (Triggering unit)) in YOUR_HASH
      • Unit Group - Remove CREEP_CREEP[NEW_UNIT] from Respawn_Group
      • Wait Respawn_Time game-time seconds
      • Unidad - Create 1 Creep_Type[NEW_UNIT] for Neutral hostil at Creep_Point[NEW_UNIT] facing Creep_Face[NEW_UNIT] degrees
      • Set Creep_Creep[NEW_UNIT] = (Last created unit)
      • Unidad - Set Creep_Creep[NEW_UNIT] acquisition range to Creep_Range[NEW_UNIT]
      • Grupo de unidad - Add Creep_Creep[NEW_UNIT] to Respawn_Group
      • Hashtable - Save NEW_UNITas 0 of (Key (Triggering unit)) in YOUR_HASH
A hashtable is kind of like an array that can use strings for indexes instead of just numbers. So in this case we saved the value of Temp_Integer for each creep (it goes up by 1 for each creep) in our hashtable, with two keys. I chose 0 for the first one since you really only need on here, but the second one is important. The second is the Handle ID of the unit (special number specific to that unit, like a unit indexer might do for you), which you can access in GUI as an integer loaded via "Hashtable - Get Handle ID". You can think of the 2 hash keys as coordinates that will tell us which creep # needs to be replaced when it dies. We stored our data in (0, <handle id of creep>).
 
Level 2
Joined
Dec 12, 2017
Messages
26
Try putting a debug message in the "Then - Actions" that will display the value of the NEW_UNIT variable when it finds a match with a creep.
  • Game - Display to (All Players) the text ("NEW_UNIT equal to "+I2S(NEW_UNIT))
My best guess is that the condition in the second trigger is never true because your units are decaying off the map super quickly and thus aren't finding a match when it searches through the stored Creeps. Honestly the better way to do this is to make a simple hashtable object to store the units. Something like:

  • -------- on map init --------
  • Hashtable - Create new hashtable
  • Set YOUR_HASH = (last created hashtable)
  • -------- --------
  • Grupo de unidad - Pick every unit in (Units in (Playable map area) owned by Neutral hostil) and do (Actions)
    • Bucle: Acciones
      • Set Temp_Integer = (Temp_Integer + 1)
      • Set Creep_Point[Temp_Integer] = (Position of (Picked unit))
      • Set Creep_Face[Temp_Integer] = (Facing of (Picked unit))
      • Set Creep_Range[Temp_Integer] = (Default acquisition range of (Picked unit))
      • Set Creep_Type[Temp_Integer] = (Unit-type of (Picked unit))
      • Set Creep_Creep[Temp_Integer] = (Picked unit)
      • Grupo de unidad - Add (Picked unit) to Respawn_Group
      • -------- vvvvv --------
      • Hashtable - Save Temp_Integer as 0 of (Key (Picked unit)) in YOUR_HASH
  • Set Respawn_Number = Temp_Integer
  • Creep Revival System Initialization Copiar Copiar Copiar
    • Acontecimientos
      • Unidad - A unit Muere
    • Condiciones
      • ((Triggering unit) is in Respawn_Group) Igual a True
    • Acciones
      • Custom script: local integer udg_NEW_UNIT
      • Set NEW_UNIT = (Load 0 of (Key (Triggering unit)) from YOUR_HASH)
      • Hashtable - Clear all child hashtables of child (Key (Triggering unit)) in YOUR_HASH
      • Unit Group - Remove CREEP_CREEP[NEW_UNIT] from Respawn_Group
      • Wait Respawn_Time game-time seconds
      • Unidad - Create 1 Creep_Type[NEW_UNIT] for Neutral hostil at Creep_Point[NEW_UNIT] facing Creep_Face[NEW_UNIT] degrees
      • Set Creep_Creep[NEW_UNIT] = (Last created unit)
      • Unidad - Set Creep_Creep[NEW_UNIT] acquisition range to Creep_Range[NEW_UNIT]
      • Grupo de unidad - Add Creep_Creep[NEW_UNIT] to Respawn_Group
      • Hashtable - Save NEW_UNITas 0 of (Key (Triggering unit)) in YOUR_HASH
A hashtable is kind of like an array that can use strings for indexes instead of just numbers. So in this case we saved the value of Temp_Integer for each creep (it goes up by 1 for each creep) in our hashtable, with two keys. I chose 0 for the first one since you really only need on here, but the second one is important. The second is the Handle ID of the unit (special number specific to that unit, like a unit indexer might do for you), which you can access in GUI as an integer loaded via "Hashtable - Get Handle ID". You can think of the 2 hash keys as coordinates that will tell us which creep # needs to be replaced when it dies. We stored our data in (0, <handle id of creep>).

Okay, good explanation about the hash tables, thanks, I modified the trigger as you said, now they respawn as they should do but only once, then they do not appear anymore, I think this are not saving the key handle of the new unit after respawning once, it's weird, thanks for the patience
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
I might have written the Hashtable clear call backwards, which would then clear the entire data structue. Try disabling the "Hashtable - Clear" line. if that gets it to work you need to switch the two keys in that line and then re-enable it.

Post the 2 triggers if that doesn't fix it.
 
Level 2
Joined
Dec 12, 2017
Messages
26
It does not work :( I'm going to post the trigger with the "Hashtable - Clear" enabled again to see if it's something I'm doing wrong:

  • Creep Revival System Initialization Copiar Copiar 2
    • Acontecimientos
      • Map initialization
    • Condiciones
    • Acciones
      • Tabla hash - Create a hashtable
      • Set YOUR_HASH = (Last created hashtable)
      • Set Respawn_Time = 5.00
      • Set Temp_Integer = 0
      • Grupo de unidad - Pick every unit in (Units in (Playable map area) owned by Neutral hostil) and do (Actions)
        • Bucle: Acciones
          • Set Temp_Integer = (Temp_Integer + 1)
          • Set Creep_Point[Temp_Integer] = (Position of (Picked unit))
          • Set Creep_Face[Temp_Integer] = (Facing of (Picked unit))
          • Set Creep_Range[Temp_Integer] = (Default acquisition range of (Picked unit))
          • Set Creep_Type[Temp_Integer] = (Unit-type of (Picked unit))
          • Set Creep_Creep[Temp_Integer] = (Picked unit)
          • Grupo de unidad - Add (Picked unit) to Respawn_Group
          • Tabla hash - Save Temp_Integer as 0 of (Key (Picked unit)) in YOUR_HASH
      • Set Respawn_Number = Temp_Integer
  • Creep Revival System Initialization Copiar Copiar Copiar
    • Acontecimientos
      • Unidad - A unit Muere
    • Condiciones
      • ((Triggering unit) is in Respawn_Group) Igual a True
    • Acciones
      • Custom script: local integer udg_NEW_UNIT
      • Set NEW_UNIT = (Load 0 of (Key (Triggering unit)) from YOUR_HASH)
      • Tabla hash - Clear all child hashtables of child (Key (Triggering unit)) in YOUR_HASH
      • Grupo de unidad - Remove Creep_Creep[NEW_UNIT] from Respawn_Group
      • Wait Respawn_Time game-time seconds
      • Unidad - Create 1 Creep_Type[NEW_UNIT] for Neutral hostil at Creep_Point[NEW_UNIT] facing Creep_Face[NEW_UNIT] degrees
      • Set Creep_Creep[NEW_UNIT] = (Last created unit)
      • Unidad - Set Creep_Creep[NEW_UNIT] acquisition range to Creep_Range[NEW_UNIT]
      • Grupo de unidad - Add Creep_Creep[NEW_UNIT] to Respawn_Group
      • Tabla hash - Save NEW_UNIT as 0 of (Key (Triggering unit)) in YOUR_HASH
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Oops this is the issue. We saved the new unit under the OLD unit's handle id!
  • Tabla hash - Save NEW_UNIT as 0 of (Key (Triggering unit)) in YOUR_HASH
  • -------- SHOULD BE AS BELOW --------
  • Tabla hash - Save NEW_UNIT as 0 of (Key (Creep_Creep[NEW_UNIT])) in YOUR_HASH
 
Level 2
Joined
Dec 12, 2017
Messages
26
Oops this is the issue. We saved the new unit under the OLD unit's handle id!
  • Tabla hash - Save NEW_UNIT as 0 of (Key (Triggering unit)) in YOUR_HASH
  • -------- SHOULD BE AS BELOW --------
  • Tabla hash - Save NEW_UNIT as 0 of (Key (Creep_Creep[NEW_UNIT])) in YOUR_HASH


Well that looks good, it must work, but when I click on Triggering Unit to change it to Creep_Creep [NEW_UNIT] the variable selector remains deactivated, how is it possible to select that variable?
I select Hashtable - Save Integer, then I click on key (triggering unit), then on Hashtable - Get HandleID I select (triggering unit) and the variable selector appears as if it did not have variables of that type, I can not find the correct option to set that (I look like an idiot xD)
 
Level 39
Joined
Feb 27, 2007
Messages
5,013
Huh, you're right that you can't do that. I'll report it to @Kam for the developer update to see if they can add that in (if nobody's mentioned it already). Instead what you can do is use "last created unit" since it's already used slightly above we know it works. If you need to save something like this again and don't have an event response GUI allows for hashtable keys, you can do
  • Custom script: set bj_lastCreatedUnit = udg_yourvariable
  • -------- Use (last created unit) which will work until a wait or new thread via ForGroup() or ForForce(). --------
  • -------- this will be reset if you create any units as the GUI sets bj_lastCreatedUnit to the new unit then. ---------
 
Level 2
Joined
Dec 12, 2017
Messages
26
Huh, you're right that you can't do that. I'll report it to @Kam for the developer update to see if they can add that in (if nobody's mentioned it already). Instead what you can do is use "last created unit" since it's already used slightly above we know it works. If you need to save something like this again and don't have an event response GUI allows for hashtable keys, you can do
  • Custom script: set bj_lastCreatedUnit = udg_yourvariable
  • -------- Use (last created unit) which will work until a wait or new thread via ForGroup() or ForForce(). --------
  • -------- this will be reset if you create any units as the GUI sets bj_lastCreatedUnit to the new unit then. ---------

Now it works perfect, really thanks for the help and patience, now I will try to implement the Threat System: D
 
Level 2
Joined
Dec 12, 2017
Messages
26
A vJASS preprocessor is the thing that turns the vJASS into regular JASS, and you get that in WEX or JNGP. So you need to download WEX, as this system is really not that hard to set up and use as you want it to function. When you find a resource like this, please just read the documentation supplied in the map. Here's what comes with his system:
JASS:
/------------------------------------------------------------------------------------------------------//
//  ZTS - ZWIEBELCHEN'S THREAT SYSTEM        v. 2.6                                                     //
//------------------------------------------------------------------------------------------------------//       
//------------------------------------------------------------------------------------------------------//
//                                                                                                      //
//  Requires: vJass Pre-Processor                                                                       //
//                                                                                                      //
//  Special thanks to TEC-Ghost, who inspired me on creating this system.                               //
//------------------------------------------------------------------------------------------------------//
//                                              MANUAL                                                  //
//------------------------------------------------------------------------------------------------------//
// 1.   How to Install:
//
//      - Create a trigger called "ZTS"
//      - Convert it to custom Text
//      - Replace everything inside with this code
//
//
// 2.   How to set it up:
//
//  2.1 Constants
//
//      There are a bunch of global constants below this manual, you can edit to your liking.
//      I commented everything you need to know about those constants right beside them. If you need additional information,
//      please tell me, so I can improve this manual. However, I think most of it should be pretty clear.
//
//  2.2. Gameplay Constants
//
//      It is recommended to edit certain Gameplay Constants entries, to use the full potential of
//      the system.
//      The most important entries are: (with selected "Show Raw-Data")
//      CallForHelp                 --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
//                                      You don't have to do it if your threat-system controlled units are neutral hostile
//      CreepCallForHelp            --> Set this to 0, if possible; the system will manage this - it isn't a problem if you don't do this, though
//      GuardDistance               --> Set this to something higher than ReturnRange (see below)
//      MaxGuardDistance            --> Set this to something higher than ReturnRange (see below)
//      GuardReturnTime             --> Set this to something very high, so that the standard AI doesn't interfere (i.e. 60 seconds)     
//
//  2.3. Damage Detection
//
//      Of course, a threat system is pretty useless without a trigger, that adds threat depending on
//      the damage dealt by a player unit.
//      I recommend using a damage detection script like IDDS:
//      (http://www.wc3c.net/showthread.php?t=100618)
//      Check up the demo map for a very simple (but leaking) damage detection trigger
//      The only function you actually need then is:
//      call ModifyThreat(GetEventDamageSource(), GetTriggerUnit(), GetEventDamage(), true)
//      The function does all required checks on its own. There is no need to run something else.
//
// 3. How to use it:
//
//  3.1. Core functions
//
//      call ZTS_AddThreatUnit(unit npc, boolean includeCombatCamps) returns nothing:
//
//          This function registers the unit as an AI-controlled unit.
//          ThreatUnits will automaticly attack the highest-in-threat attacker.
//          When adding a ThreatUnit, its current position gets saved and be considered camp-position.
//          It will always return to this position if pulled to far or on victory.
//          Nearby units will be considered in the same camp group. Camp members will always retreat and attack together.
//          If includeCombatCamps is true, the unit will be added to already fighting camps. If it is false, the unit will
//          create its own camp group, if it can't find any non-fighting units nearby.
//          This should be false in most cases, but it can be useful when you have bosses that summon units infight, so that
//          the summons will be added to the bossfight correctly instead of getting their own seperate group.
//
//      call ZTS_AddPlayerUnit(unit pu) returns nothing:
//
//          Units add by this way will generate threat on ThreatUnits.
//          If the unit is not registered as a PlayerUnit, it will not be attacked by ThreatUnits.
//
//      call ZTS_RemoveThreatUnit(unit npc) returns nothing:
//
//          Removes a ThreatUnit from the system. The unit will no longer be controlled by the threat system.
//          Also, the threat list for that unit will be cleared.
//          Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
//      call ZTS_RemovePlayerUnit(unit pu) returns nothing:
//
//          Removes a player unit from the system. The unit will no longer generate threat on ThreatUnits.
//          The unit will also be instantly removed from all threat lists.
//          If the unit was the last unit in combat with the same hostile camp, all units
//          of that camp group will immediately return to their camp positions.
//          You can use this, followed by AddPlayerUnit to that unit out of combat and reset all threat.
//          Dead or removed units will automaticly be cleared. You need to add them again after revival/recreation.
//
//      call ZTS_ModifyThreat(unit pu, unit npc, real amount, boolean add) returns nothing:
//
//          Adds, sets or substracts threat from npc's threat list caused by pu.
//          Set 'add' to true to add or substract amount from the current value.
//          Set 'add' to false to set the new threat value to amount.
//          To reduce threat, use negative amount values with add == true.
//          Remember: If a unit has 0 threat, it is still considered in-combat -
//          this also means, that adding "0" to the units threat causes them to attack!
//
//      call ZTS_ApplyHealThreat(unit pu, unit ally, real amount, boolean add, boolean divide) returns nothing:
//
//          Adds Healing Threat to all units, that have ally on threat-list
//          This can be abused to apply global threat to a unit by passing the same unit to p and ally.
//          Parameter divide = true means that the amount is split by the number of units attacking the target;
//          for example if 3 units are currently attacking the targeted ally, it adds amount/3 threat from pu to all of them.
//          Parameter divide = false means that every attacking unit gets 'amount' of threat applied.
//          use add = false to set the amount of threat to 'amount', instead of increasing/decreasing it
//          negative values are allowed in combination with 'add' to reduce threat.
//          You can also use this with add = false and amount = 0 with pu = ally to set total threat generated back to zero for this unit.
//
//
//  3.2. Getter functions
//
//      call ZTS_GetCombatState(unit U) returns boolean:
//
//          Returns the combat state of a player or npc unit.
//          Returns true, if the unit is registered and in combat.
//          Returns false, if the unit is not registered or out of combat.
//
//      call ZTS_GetCombatTime(unit NPC) returns boolean:
//
//          Returns the incombat time of the npc.
//          Does not work for player units.
//          Returns "0" if the unit is not in combat or currently returning to camp position.
//
//      call ZTS_GetThreatUnitPosition(unit NPC, unit PU) returns integer:
//
//          Returns the position of unit PU in unit NPC's threat list
//          Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
//      call ZTS_GetThreatUnitAmount(unit NPC, unit PU) returns real:
//
//          Returns the amount of threat unit PU has in unit NPC's threat list
//          Returns "0" if the unit was not found, NPC does not feature a threat list or in case of invalid input data
//
//      call ZTS_GetThreatSlotUnit(unit NPC, integer position) returns unit:
//
//          Returns the unit in threat-slot position
//          Returns null if the NPC does not feature a threat list, the number is too large
//          or in case of invalid input data
//
//      call ZTS_GetThreatSlotAmount(unit NPC, integer position) returns real:
//
//          Returns the threat amount of the threat-slot position
//          Returns "0" if the NPC does not feature a threat list, the number is too large
//          or in case of invalid input data
//
//      call ZTS_GetAttackers(unit U) returns group:
//
//          If used on a ThreatUnit, this returns a group of all units in threat list;
//          if used on a PlayerUnit, this returns a group of all units aggroed.
//          Returns an empty group, in case of invalid input data or empty lists.
//
//
//  3.3. Advanced User features
//
//      call ZTS_IsEvent() returns boolean
//
//          When using "A unit is issued an order without target" or "A unit is issued a target order" events,
//          this function returns true when the order was issued by the threat system.
//          You can use this to setup your own spell-AI for units.
//          Let's say you want the unit to cast Summon Water Elemental whenever the cooldown is ready:
//          Just use the mentioned events and add:
//              Custom script:   if not ZTS_IsEvent() then
//              Custom script:   return
//              Custom script:   endif
//          at the beginning of you trigger's actions and you're done.
//          You can now issue the order to the triggering unit:
//              Unit - Order (Triggering unit) to Human Archmage - Summon Water Elemental
//          In combination with some of the Getter functions, you can trigger nice spell AI like this.
//          NOTE: ZTS_IsEvent will only return true once(!) for every fired event, so if you need it again inside that trigger,
//                make sure to save it to a variable.
//
//------------------------------------------------------------------------------------------------------//

library ZTS initializer InitThreatSystem

globals 
    private constant real UpdateIntervall = 0.5 //The intervall for issueing orders and performing AttackRange check. recommended value: 0.5
    private constant real HelpRange = 400 //The range between units considered being in the same camp. If a unit of the same camp gets attacked, all others will help.
                                          //Set CallForHelp to something lower in Gameplay Constants.
    private constant real OrderReturnRange = 4000 //The range the unit's target can be away from the original camping position, before being ordered to return.
    private constant real ReturnRange = 1500 //The range the unit can move away from the original camping position, before being ordered to return.
    private constant real TimeToPort = 10 //This timer expires once a unit tries to return to its camping position.
                                          //If it reaches 0 before reaching the camp position, the unit will be teleported immediately.
    private constant boolean HealUnitsOnReturn = true //If this is true, returning units will be healed to 100% health.
 
 
//      Do not edit below here!
//------------------------------------------------------------------------------------------------------//
So to make it work in your map the entirety of what you have to do is:
  1. Import a damage detect system into your map (there are a few here that run in GUI like GDD)
  2. Configure the imported DDS as its documentation outlines you should do
  3. Copy over the ZTS trigger into your map, thus importing his threat system
  4. Configure the little bit of ZTS you have to (maybe you don't change it all, idk)
  5. Figure out how to use your DDS to run something (probably a trigger with no events) when a unit takes damage, and copy over the custom script line from the "DamageDetect" trigger in the ZTS map. This is what tells the game to add threat when units take damage. The DDS you pick might specify variables to use to get targeted units/damage or might say to use the GetTriggerUnit() syntax that's already there. You should be able to figure this out from example code in the DDS you pick, but post if you're confused.
  6. Make your own trigger like his "Init" trigger that sets up units into the ZTS system. You don't have to use the trigger add action loop, just pick every unit you want to behave like it has threat (all creeps) and do that custom script call. Do the same for player units (things that should generate threat). Again ask if confused.

Finally I was able to implement the threat system of Zwiebelchen perfectly, I was able to use all its functions and it's a wonder, thanks to you Pyrogasm
 
Status
Not open for further replies.
Top