Jesus4Lyf
Good Idea™
- Reaction score
- 397
Abduct
Version 1.02
Requirements:
- Jass NewGen
- AIDS
- Transport
Code:
JASS:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// ~~ Abduct ~~ By Jesus4Lyf ~~ Version 1.02 ~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// What is Abduct?
// - Abduct allows a unit to load units of an enemy player.
//
// Functions:
// - SetAbductCapacity(unit, integer)
// Sets the number of units a unit may abduct successfully
// at once. Use a number from 1 to 8, excluding 7. Warcraft III
// does not allow a transport to have a maximum capacity of 7.
//
// - GetAbductCapacity(unit)
// Returns the abduction capacity (integer) of the unit, based on
// SetAbductCapacity.
//
// - RemoveAbductCapacity(unit)
// Disallows a unit to abduct other units.
//
// - Abduct(abductor, target)
// Returns a boolean of success. This success is anticipated.
// There is a slight delay until the unit is actually abducted.
// Use this to load an enemy unit into a transport. It will
// interrupt the transport's current order.
//
// Details:
// - Abduct changes the target's owner for a small amount of time while
// it is loaded into the abductor. It then changes ownership back.
//
// How to import:
// - Create a trigger named Abduct.
// - Convert it to custom text and replace the whole trigger text with this.
// - Save the map, close it, reopen it, and then delete the "!" from the
// FAR left side of the next lines (so "external" will line up with this line):
//! external ObjectMerger w3a Sch3 AACG ansf "(Abduct System)" aefs "" alev 8 Car1 1 1 Car1 2 2 Car1 3 3 Car1 4 4 Car1 5 5 Car1 6 6 Car1 7 7 Car1 8 8 aare 1 0 ahdu 1 0 adur 1 0 aran 1 99999 aran 2 99999 aran 3 99999 aran 4 99999 aran 5 99999 aran 6 99999 aran 7 99999 aran 8 99999 atar 1 "friend,ground,invulnerable,vulnerable" atar 2 "friend,ground,invulnerable,vulnerable" atar 3 "friend,ground,invulnerable,vulnerable" atar 4 "friend,ground,invulnerable,vulnerable" atar 5 "friend,ground,invulnerable,vulnerable" atar 6 "friend,ground,invulnerable,vulnerable" atar 7 "friend,ground,invulnerable,vulnerable" atar 8 "friend,ground,invulnerable,vulnerable" aare 1 256 aare 2 256 aare 3 256 aare 4 256 aare 5 256 aare 6 256 aare 7 256 aare 8 256
//! external ObjectMerger w3a Aloa AALD ansf "(Abduct System)" aran 1 99999
//
// Thanks:
// - Weep, for reporting the Mac unload bug and suggesting a resolution.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
library Abduct initializer OnInit uses AIDS, Transport optional DummyCaster
globals
private constant integer ABIL_CARGO=039;AACG039;
private constant integer ABIL_LOAD=039;AALD039;
private constant integer OID_LOAD=852046
endglobals
private struct Data extends array
// Abductee
player previousOwner
// Abductor
unit target
integer capacity
private method AIDS_onDestroy takes nothing returns nothing
// Abductee
if this.target!=null then
call SetUnitOwner(this.target,Data[this.target].previousOwner,false)
set this.target=null
endif
// Abductor
set this.capacity=0
endmethod
//! runtextmacro AIDS()
endstruct
function GetAbductCapacity takes unit u returns integer
return Data<u>.capacity
endfunction
globals//locals
private Data OrderedData
endglobals
private function OnAnyOrder takes nothing returns boolean
// Safety.
set OrderedData=Data[GetTriggerUnit()]
if OrderedData.target!=null then
if GetIssuedOrderId()!=OID_LOAD or GetOrderTargetUnit()!=OrderedData.target then
call SetUnitOwner(OrderedData.target,Data[OrderedData.target].previousOwner,false)
call UnitRemoveAbility(OrderedData.unit,ABIL_LOAD)
set OrderedData.target=null
endif
endif
return false
endfunction
globals//locals
private Data LoadedData
private Data LoadingData
endglobals
private function OnLoad takes nothing returns boolean
set LoadedData=Data[GetTriggerUnit()]
set LoadingData=Data[GetTransportUnit()]
if LoadingData.target==LoadedData.unit then
set LoadingData.target=null
call SetUnitOwner(LoadedData.unit,LoadedData.previousOwner,false)
call UnitRemoveAbility(LoadingData.unit,ABIL_LOAD)
endif
return false
endfunction
globals
private Data AbducteeData
private Data AbductorData
endglobals
function Abduct takes unit abductor, unit abductee returns boolean
set AbductorData=Data[abductor]
if Transport_CountPassengers(abductor)>=AbductorData.capacity then
return false
endif
set AbducteeData=Data[abductee]
// So it can be loaded.
set AbducteeData.previousOwner=GetOwningPlayer(abductee)
call SetUnitOwner(abductee,GetOwningPlayer(abductor),false)
call UnitAddAbility(abductor,ABIL_LOAD)
if IssueTargetOrderById(abductor,OID_LOAD,abductee) then
if AbductorData.target!=null then
call SetUnitOwner(AbductorData.target,Data[AbductorData.target].previousOwner,false)
endif
set AbductorData.target=abductee
return true
endif
// upon failure
call SetUnitOwner(abductee,AbducteeData.previousOwner,false)
call UnitRemoveAbility(abductor,ABIL_LOAD)
return false
endfunction
function SetAbductCapacity takes unit u, integer cargo returns nothing
debug if cargo==7 then
debug call BJDebugMsg("Transport: WARNING! 7 is an invalid transport capacity in Warcraft III.")
debug endif
call UnitAddAbility(u,ABIL_CARGO)
set Data<u>.capacity=SetUnitAbilityLevel(u,ABIL_CARGO,cargo)
endfunction
function RemoveAbductCapacity takes unit u returns nothing
call UnitRemoveAbility(u,ABIL_CARGO)
set Data<u>.capacity=0
endfunction
private function OnInit takes nothing returns nothing
local trigger t
// Preload
static if LIBRARY_DummyCaster then
if UnitAddAbility(DUMMY,ABIL_LOAD) then
call UnitRemoveAbility(DUMMY,ABIL_LOAD)
endif
if UnitAddAbility(DUMMY,ABIL_CARGO) then
call UnitRemoveAbility(DUMMY,ABIL_CARGO)
endif
else
local unit u=CreateUnit(Player(15),039;uloc039;,0,0,0)
call UnitAddAbility(u,ABIL_LOAD)
call UnitAddAbility(u,ABIL_CARGO)
call RemoveUnit(u)
set u=null
endif
// On load event.
set t=CreateTrigger()
call TriggerAddCondition(t,Filter(function OnLoad))
call Transport_RegisterLoadEvent(t)
// On any order.
set t=CreateTrigger()
call TriggerAddCondition(t,Filter(function OnAnyOrder))
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ISSUED_ORDER)
set t=null
endfunction
endlibrary
</u></u></u>
This allows you to force load an enemy unit into a transport unit. It makes a good replacement for Devour, as you can trigger the effects yourself, and unload the loaded units at will instead of forcing them to remain until they die. It also allows you to load multiple units at once (unlike Devour). In addition, you can call this from whatever context you like (not just as an ability).
Example:
Add a single footman to a map and it will abduct enemies instead of attack them with this code.
JASS:
scope AbductDemo initializer OnInit
private function OnAttack takes nothing returns boolean
if Abduct(GetAttacker(),GetTriggerUnit()) then
call BJDebugMsg(GetUnitName(GetAttacker())+" has abducted "+GetUnitName(GetTriggerUnit())+".")
else
call BJDebugMsg(GetUnitName(GetAttacker())+" failed to abduct "+GetUnitName(GetTriggerUnit())+".")
endif
return false
endfunction
private function OnInit takes nothing returns nothing
local trigger t=CreateTrigger()
local unit footman=GroupPickRandomUnit(GetUnitsOfTypeIdAll(039;hfoo039;))
call SetAbductCapacity(footman,2)
call TriggerRegisterAnyUnitEventBJ(t,EVENT_PLAYER_UNIT_ATTACKED)
call TriggerAddCondition(t,Filter(function OnAttack))
endfunction
endscope
Updates:
- Version 1.02: Fixed a bug where Mac users could not unload Abducted units. Fixed a typo in a debug message.
- Version 1.01: Added GetAbductCapacity and optional DummyCaster use for preloading.
- Version 1.00: Release.