• 🏆 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] Undroppable items trigger

Status
Not open for further replies.

ies

ies

Level 2
Joined
Jun 11, 2019
Messages
5
Hello,
I'm trying to fix healing abuse in a map by preventing players from dropping their life boosting items before restoring their hero's life.
The items should remain movable in inventory and droppable in base.
(Game version is 1.27 with ydwe support.)

I setup a trigger that looks for 'EVENT_PLAYER_UNIT_DROP_ITEM'; removes the item and then returns the item back to the unit which triggered it.

This is what I have in my trigger actions (no idea what I'm doing, never used this).
JASS:
local integer it=GetItemTypeId(GetManipulatedItem())
call RemoveItem(GetManipulatedItem())
call UnitAddItemById(GetTriggerUnit(),it)
It worked, but for some reason, it triggered 6 times. Putting PolledWait(.1) before the calls fixed that issue. Putting it after RemoveItem caused the item being added infinitely, big question mark.

Question: The event is firing on items sold to vendor and items passed to another unit and possibly something else I'm not thinking of. How do I filter these? Items sold should be ignored and items passed between units need to have their own countermeasure.

Whole trigger simplified
JASS:
function InitTrig_abuse takes nothing returns nothing
set gg_trg_abuse=CreateTrigger()
call TriggerRegisterPlayerUnitEvent(gg_trg_abuse,Player(0),EVENT_PLAYER_UNIT_DROP_ITEM,null)
call TriggerAddCondition(gg_trg_abuse,Condition(function Trig_abuseConditions))
call TriggerAddAction(gg_trg_abuse,function Trig_abuseActions)
endfunction

function Trig_abuseActions takes nothing returns nothing
local integer it=GetItemTypeId(GetManipulatedItem())
call PolledWait(.01)
call RemoveItem(GetManipulatedItem())
call UnitAddItemById(GetTriggerUnit(),it)
endfunction

function Trig_abuseConditions takes nothing returns boolean
return true
endfunction
 
Level 20
Joined
Feb 27, 2019
Messages
593
If you can make one or two formulas to calculate new hp after an item is acquired/dropped you can remove the percentual hp change completely. Then players cant abuse the items and you dont have to think about other scenarios like items being sold to merchants.

That would mean that if you acquire/drop an item that gives 150 hp youll have no change in hp, only max hp will change.
 

ies

ies

Level 2
Joined
Jun 11, 2019
Messages
5
If you can make one or two formulas to calculate new hp after an item is acquired/dropped you can remove the percentual hp change completely. Then players cant abuse the items and you dont have to think about other scenarios like items being sold to merchants.

That would mean that if you acquire/drop an item that gives 150 hp youll have no change in hp, only max hp will change.
Oh, thank you, that is quite more efficient approach.
Can I somehow hash the life value from EVENT_PLAYER_UNIT_PICKUP_ITEM before the item applies its stats?
 
Last edited:
Level 20
Joined
Feb 27, 2019
Messages
593
Oh, thank you, that is quite more efficient approach.
Can I somehow hash the life value from EVENT_PLAYER_UNIT_PICKUP_ITEM before the item applies its stats?
Not really in the way one would like. There are other ways to do it though.

One way is to remove the abilities from the items all together and add the bonuses in some other way. For example its very easy to change max hp of a unit. In the newer versions you can change the value of an ability, so to change strength one would only need to add a permanent ability to a unit then change the strength value of that ability as well as "refresh" passives by increasing and decreasing a level of the ability. This does not work in older versions. I heard they used to have 32 abilities of the same kind in a binary system. So the first ability would give +1, the second +2, third +4 and so on. Combining the first with the second would give +3. Seems a bit tedious though. Here is a simple system to add max hp.
  • Item Init
    • Events
      • Time - Elapsed game time is 0.00 seconds
    • Conditions
    • Actions
      • -------- Khadgar's Gem of Health --------
      • Set VariableSet BonusHP[1] = 300
      • -------- Periapt of Vitality --------
      • Set VariableSet BonusHP[2] = 150
  • Item Acquire
    • Events
      • Unit - A unit Acquires an item
    • Conditions
    • Actions
      • Custom script: local unit u = GetTriggerUnit()
      • Custom script: local integer itemId = GetItemTypeId(GetManipulatedItem())
      • -------- Khadgar's Gem of Health --------
      • Custom script: if ( itemId == 'rhth' ) then
      • Custom script: call BlzSetUnitMaxHP( u, ( BlzGetUnitMaxHP(u) + udg_BonusHP[1] ) )
      • -------- Periapt of Vitality --------
      • Custom script: elseif ( itemId == 'prvt' ) then
      • Custom script: call BlzSetUnitMaxHP( u, ( BlzGetUnitMaxHP(u) + udg_BonusHP[2] ) )
      • Custom script: endif
      • Custom script: set u = null
  • Item Lose
    • Events
      • Unit - A unit Loses an item
    • Conditions
    • Actions
      • Custom script: local unit u = GetTriggerUnit()
      • Custom script: local integer itemId = GetItemTypeId(GetManipulatedItem())
      • -------- Khadgar's Gem of Health --------
      • Custom script: if ( itemId == 'rhth' ) then
      • Custom script: call BlzSetUnitMaxHP( u, ( BlzGetUnitMaxHP(u) - udg_BonusHP[1] ) )
      • -------- Periapt of Vitality --------
      • Custom script: elseif ( itemId == 'prvt' ) then
      • Custom script: call BlzSetUnitMaxHP( u, ( BlzGetUnitMaxHP(u) - udg_BonusHP[2] ) )
      • Custom script: endif
      • Custom script: set u = null
Another way to do it is a more general way. If an item is picked up I move it onto the map so that the unit does not get any bonus and I can get the life value "before" the item is picked up. Moving or removing an item from a units inventory is basically the same as dropping the item so instantly moving it again would mean the event for dropping the item fires so I need to disable the trigger that runs when the item is dropped. I can also use a boolean to stop the trigger from running. The same goes when the item is given back to the units inventory after which I can set its life to the value "before".

I ran into a small problem with power ups and sold items. This is because the item is not recognized as having 0.00 hp or being removed until it has officially left the units inventory which happens after a game tic. This is why you had to add 0.01 polled wait. I fixed it by filtering out power ups and remove sold items. Keep in mind that removing sold items will cause problems if you want to reference a sold item in another trigger. Another way that I think could be used to fix it is to start a timer at 0.00 seconds and continue the actions after the event "timer expires". That happens almost instantly and is much faster and accurate than using a polled wait. After that time, a sold item and power up item would have 0.00 hp.
  • Acquire
    • Events
      • Unit - A unit Acquires an item
    • Conditions
      • ItemEventBlock Equal to False
      • (Item-class of (Item being manipulated)) Not equal to Powerup
    • Actions
      • Custom script: local real r
      • Custom script: local unit u = GetTriggerUnit()
      • Custom script: local item i = GetManipulatedItem()
      • Set VariableSet ItemEventBlock = True
      • Custom script: call SetItemPosition( i, 0, 0 )
      • Custom script: set r = GetUnitStateSwap(UNIT_STATE_LIFE, u)
      • Custom script: call UnitAddItemSwapped( i, u )
      • Custom script: call SetUnitLifeBJ( u, r )
      • Set VariableSet ItemEventBlock = False
      • Custom script: set u = null
      • Custom script: set i = null
  • Lose
    • Events
      • Unit - A unit Loses an item
    • Conditions
      • ItemEventBlock Equal to False
    • Actions
      • Custom script: local real r
      • Custom script: local unit u = GetTriggerUnit()
      • Custom script: local item i = GetManipulatedItem()
      • Custom script: local real x = GetItemX(i)
      • Custom script: local real y = GetItemY(i)
      • Set VariableSet ItemEventBlock = True
      • Custom script: call UnitAddItemSwapped( i, u )
      • Custom script: set r = GetUnitStateSwap(UNIT_STATE_LIFE, u)
      • Custom script: call SetItemPosition( i, x, y )
      • Custom script: call SetUnitLifeBJ( u, r )
      • Set VariableSet ItemEventBlock = False
      • Custom script: set u = null
      • Custom script: set i = null
  • Pawn
    • Events
      • Unit - A unit Pawns an item (to shop)
    • Conditions
    • Actions
      • Item - Remove (Sold Item)
 
Status
Not open for further replies.
Top