|
|
|
|
Submissions Submit JASS resources! If approved, they will be moved to their proper section. Please read me first. |
 |
|
07-05-2012, 03:19 PM
|
#1 (permalink)
|
|
SSJ99999 Pinoy!
Join Date: Mar 2009
Posts: 4,385
|
TrainSystem
TrainSystem v1.3
This system is used in my map and works quite well, I want to test it here...
What the hell is this?
- Auto trains a unit one at a time
- This is more dynamic than GUI AI editor as it doesnt recognize priorities, it will train random units
- If the unit is not yet available or needs food/gold/lumber, it will not count the limit
- Limits the number of units trained by a particular structure
Jass:
/*
=====Train System v1.3
=====By Mckill2009
This is a system in which your building will automatically train a unit, this is good for
AI's or computer players...
REQUIRED NATIVE ABOVE MAP SCRIPT:
native UnitAlive takes unit u returns boolean
API:
static method register takes unit source, integer limit returns nothing
- first thing to do
- registers your source unit that will automatically train units
- sets the initial limit to train units
static method addTrain takes unit source, integer trainedID returns nothing
- second thing to do
- source - the unit that will be training
- trainedID - the unittypeID of the unit being trained
- the more trainedID you register, the higher the probability it will be trained in the list
static method setLimit takes unit source, integer limit returns nothing
- sets/adds the limit of your units being trained
- the limit must be greater than the limit from initial setup (from register)
static method removeTrain takes unit source returns nothing
- removes the source from the list or stops the auto train
static method clearAll takes nothing returns nothing
- removes all units from the list
- destroys the ID's and starts a fresh one
CREDITS:
- Table by Bribe
- RegisterPlayerUnitEvent by Magtheridon96
OTHER CREDITS:
Magtheridon96 (for suggestions)
Troll-Brain (for tests)
*/
library TrainSystem uses Table, RegisterPlayerUnitEvent
struct TrainSystem
unit source
static constant integer maxInstance = 8190
static constant integer childID = 1000
static integer instance = 0
static integer array instanceAr
static timer t = CreateTimer()
static real interval = 1.0
static Table lim //limit of units trained by a particular structure
static Table chk //checks the counter of the trained unit
static Table tra //trained unit reduce counter
static TableArray random
private static method looper takes nothing returns nothing
local thistype this
local integer looper = 0
local integer i
local integer ID
local integer ran
local integer array ar
loop
set looper = looper + 1
set this = instanceAr[looper]
set ID = GetHandleId(.source)
if UnitAlive(.source) and chk.has(ID) then
if (lim[ID]) > (chk[ID]) and chk.boolean[ID] then
set i = 0
loop
set i = i + 1
set ar[i] = random[i][ID]
exitwhen i==random[childID][ID] //maxINDEX
endloop
set ran = GetRandomInt(1,random[childID][ID])
if IssueImmediateOrderById(.source, ar[ran]) then
set chk.boolean[ID] = false
endif
endif
else
call chk.remove(ID)
set .source = null
call .destroy()
set instanceAr[looper] = instanceAr[instance]
set instanceAr[instance] = this
set looper = looper - 1
set instance = instance - 1
if instance==0 then
call PauseTimer(t)
endif
endif
exitwhen looper==instance
endloop
endmethod
private static method deathEvent takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit source //the source that trains the dying unit
local integer ID = GetHandleId(u)
local integer sourceID
if u==tra.unit[ID] then
set source = chk.unit[ID]
set sourceID = GetHandleId(source)
set chk[sourceID] = chk[sourceID] - 1
set chk.boolean[sourceID] = true
call tra.remove(ID)
set source = null
endif
set u = null
endmethod
private static method trainCancel takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit trained = GetTrainedUnit()
local integer ID = GetHandleId(u)
if not chk.boolean[ID] then
set chk.boolean[ID] = true
set chk[ID] = chk[ID] - 1
endif
set u = null
set trained = null
endmethod
private static method trainEnd takes nothing returns nothing
local unit u = GetTriggerUnit()
local unit trained = GetTrainedUnit()
local integer ID = GetHandleId(u)
local integer trID = GetHandleId(trained)
if chk.has(ID) then
set chk[ID] = chk[ID] + 1
set chk.boolean[ID] = true
set chk.unit[trID] = u
set tra.unit[trID] = trained
endif
set u = null
set trained = null
endmethod
private static method onInit takes nothing returns nothing
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_TRAIN_CANCEL, function thistype.trainCancel)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_TRAIN_FINISH, function thistype.trainEnd)
call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_DEATH, function thistype.deathEvent)
set lim = Table.create()
set chk = Table.create()
set tra = Table.create()
set random = TableArray[0x2000]
endmethod
//API's==============================
static method register takes unit source, integer limit returns nothing
local integer ID = GetHandleId(source)
local thistype this
if chk.has(ID) then
debug call BJDebugMsg("register ERROR: "+GetUnitName(source)+" is already registered!")
else
if instance==maxInstance then
debug call BJDebugMsg("register ERROR: Unable to allocate more than "+I2S(maxInstance)+" instance.")
call DestroyTimer(t)
else
set this = allocate()
set .source = source
set lim[ID] = limit
set chk[ID] = 0 //checks the limit
set chk.boolean[ID] = true //cheks if registered or not
if instance==0 then
set t = CreateTimer()
call TimerStart(t,interval,true,function thistype.looper)
endif
set instance = instance + 1
set instanceAr[instance] = this
endif
endif
endmethod
static method addTrain takes unit source, integer trainedID returns nothing
local integer ID = GetHandleId(source)
local integer index
if chk.has(ID) then
set random[childID][ID] = random[childID][ID]+1 //maxINDEX
set index = random[childID][ID]
set random[index][ID] = trainedID //so that all trainedID will be saved in a unique index
else
debug call BJDebugMsg("addTrain ERROR: Please register "+GetUnitName(source)+" first.")
endif
endmethod
static method setLimit takes unit source, integer limit returns nothing
local integer ID = GetHandleId(source)
if chk.has(ID) then
if (limit) > (lim[ID]) then
set lim[ID] = limit
else
debug call BJDebugMsg("setLimit ERROR: Limit must be greater than registered value!")
endif
else
debug call BJDebugMsg("addLimit ERROR: "+GetUnitName(source)+" is not registered!")
endif
endmethod
static method removeTrain takes unit source returns nothing
local integer ID = GetHandleId(source)
if chk.has(ID) then
call lim.remove(ID)
call chk.remove(ID)
set random[childID][ID] = 0
else
debug call BJDebugMsg("removeTrain ERROR: "+GetUnitName(source)+" is not registered!")
endif
endmethod
static method clear takes nothing returns nothing
call PauseTimer(t)
call DestroyTimer(t)
call random.destroy()
call lim.destroy()
call chk.destroy()
call tra.destroy()
set instance = 0
set lim = Table.create()
set chk = Table.create()
set tra = Table.create()
set random = TableArray[0x2000]
endmethod
endstruct
endlibrary
 DEMO   Events   Conditions   Actions    Set U = Barracks 0035 <gen>    Custom script: call TrainSystem.register(udg_U, 5)    Custom script: call TrainSystem.addTrain(udg_U, 'hfoo')    Custom script: call TrainSystem.addTrain(udg_U, 'hrif')    Set U = Barracks 0036 <gen>    Custom script: call TrainSystem.register(udg_U, 5)    Custom script: call TrainSystem.addTrain(udg_U, 'hfoo')    Custom script: call TrainSystem.addTrain(udg_U, 'hrif')    Set U = Arcane Sanctum 0039 <gen>    Custom script: call TrainSystem.register(udg_U, 5)    Custom script: call TrainSystem.addTrain(udg_U, 'hmpr')    Custom script: call TrainSystem.addTrain(udg_U, 'hsor')    Set U = Arcane Sanctum 0040 <gen>    Custom script: call TrainSystem.register(udg_U, 5)    Custom script: call TrainSystem.addTrain(udg_U, 'hmpr')    Custom script: call TrainSystem.addTrain(udg_U, 'hsor')    Set U = Gryphon Aviary 0037 <gen>    Custom script: call TrainSystem.register(udg_U, 5)    Custom script: call TrainSystem.addTrain(udg_U, 'hgry')    Custom script: call TrainSystem.addTrain(udg_U, 'hdhw')    Set U = Gryphon Aviary 0038 <gen>    Custom script: call TrainSystem.register(udg_U, 5)    Custom script: call TrainSystem.addTrain(udg_U, 'hgry')    Custom script: call TrainSystem.addTrain(udg_U, 'hdhw')
__________________
My Resources:
My Maps
My Systems/Spells
Your ideas tend to result in unnecessary violence so shut the F*** up!
Last edited by mckill2009; 09-03-2012 at 10:15 AM.
|
|
|
07-05-2012, 03:28 PM
|
#2 (permalink)
|
|
cool != useful
Join Date: Apr 2008
Posts: 1,937
|
You know that the event CANCEL doesn't always fire when it should ?
Like when you click on the icon of the unit which is being trained, probably also when you press escape and/or click on the cancel button.
__________________
- There are bugs with wc3, but most of time, the bug is between the keyboard and the chair.
- Never believe some warcraft "fact" without a proof, even from an "experienced" user, that's how myths & legends born.
You spam "...", "lol", and smilies such as "; p", "^)^",">.>"? You think you're the best and all other ones are stupids or at least less clever than you ? You think your errors are funny, while the other ones are incredibly lame ?
Maybe you've too much ego,or worse, you're a douchebag
|
|
|
07-05-2012, 03:48 PM
|
#3 (permalink)
|
|
SSJ99999 Pinoy!
Join Date: Mar 2009
Posts: 4,385
|
I didnt know that but this I dont think so coz I tested the CANCEL and ESC already and the
the
chk[ID]
seems to be OK...I've added a testmap...
__________________
My Resources:
My Maps
My Systems/Spells
Your ideas tend to result in unnecessary violence so shut the F*** up!
|
|
|
07-05-2012, 04:13 PM
|
#4 (permalink)
|
|
JESUS MAN
Resource Moderator
Join Date: Dec 2008
Posts: 5,700
|
I like trains
edit
Oh wait, that's not what this system is about ;_;
edit
You don't need the native declaration because Bribe confirmed that UnitAlive returns the same thing as (not IsUnitType(u, UNIT_TYPE_DEAD)).
edit
In the deathEvent function, it would be best to cache the handle ids of b and u.
And in the trainEnd function, it would be best to cache the handle id of the trained unit.
edit
Also, 0x30000 is too large a TableArray size for what you're doing here ;P
0x2000 == 8192 and it too is very large :P
Go for 0x2000 or less
|
|
|
07-05-2012, 04:17 PM
|
#5 (permalink)
|
|
cool != useful
Join Date: Apr 2008
Posts: 1,937
|
Quote:
Originally Posted by mckill2009
I didnt know that but this I dont think so coz I tested the CANCEL and ESC already and the
the
chk[ID]
seems to be OK...I've added a testmap...
|
Maybe the bug was fixed, but i don't think so, the test is simple just display a text message on CANCEL event and try to cancel a training unit by clicking on its icon, clicking the red cancel button and finally by pressing esc.
Now, that wouldn't be a problem for computers, it's just an issue about real human players.
But if what i say it's true (most likely) then you should really say it in your documentation, because it's such an obscure bug.
I know you don't recommend that for real human players though.
EDIT : Or it's just about when you have several units in a same training queue, i don't really remember.
__________________
- There are bugs with wc3, but most of time, the bug is between the keyboard and the chair.
- Never believe some warcraft "fact" without a proof, even from an "experienced" user, that's how myths & legends born.
You spam "...", "lol", and smilies such as "; p", "^)^",">.>"? You think you're the best and all other ones are stupids or at least less clever than you ? You think your errors are funny, while the other ones are incredibly lame ?
Maybe you've too much ego,or worse, you're a douchebag
|
|
|
07-05-2012, 04:27 PM
|
#6 (permalink)
|
|
Dance, my puppets, dance!
Join Date: Sep 2009
Posts: 2,294
|
Damn I was expecting a system that uses destructable railroads to define an automated path for units placed on it... :(
|
|
|
07-05-2012, 04:46 PM
|
#7 (permalink)
|
|
cool != useful
Join Date: Apr 2008
Posts: 1,937
|
AutoTrain would fit more for this resource ? (it's actually a question)
For me a system = code + something else (most likely something related to the object editor, but it can be also a custom sound, whatever ...)
__________________
- There are bugs with wc3, but most of time, the bug is between the keyboard and the chair.
- Never believe some warcraft "fact" without a proof, even from an "experienced" user, that's how myths & legends born.
You spam "...", "lol", and smilies such as "; p", "^)^",">.>"? You think you're the best and all other ones are stupids or at least less clever than you ? You think your errors are funny, while the other ones are incredibly lame ?
Maybe you've too much ego,or worse, you're a douchebag
|
|
|
07-06-2012, 12:16 AM
|
#8 (permalink)
|
|
SSJ99999 Pinoy!
Join Date: Mar 2009
Posts: 4,385
|
@Mags
well noted for handle cache and size of array (although nothing wrong with it)...
@Troll- Brain
I did a msg check after
set chk[ID] = chk[ID] + 1
and it keeps on
displaying the same number when I cancel/esc...
anyway I may put condition that it can only add computer players if that bug
you say still exist...
I forgot to add an API to unregister the unit...and thanks for the name suggestion...
__________________
My Resources:
My Maps
My Systems/Spells
Your ideas tend to result in unnecessary violence so shut the F*** up!
|
|
|
07-06-2012, 04:16 PM
|
#9 (permalink)
|
|
cool != useful
Join Date: Apr 2008
Posts: 1,937
|
Well, i've never said it and it's off-topic but plz stop to abuse "..." it's really hard to get your feelings.
Usually we use "..." as "etc", or as a sarcasm, or get bored, but i can't believe that you're always sarcastic/bored.
Anyway i'm quite sure of what i said, there are three ways to remove an unit which is being trained (i mean in game as a player).
I will check them and share a test map and a replay since you keep saying it's fine.
Again the bug could be fixed now but that's very unlikely.
EDIT : Ok it's either that the bug was silently fixed in some patch or the bug was nothing but me, the event always fire except when the structure is killed/removed, this was tested with the patch 1.26a.
If one day i have to make an other test before the patch of the dead (end of the return bug) i will test it just for the sake of it.
__________________
- There are bugs with wc3, but most of time, the bug is between the keyboard and the chair.
- Never believe some warcraft "fact" without a proof, even from an "experienced" user, that's how myths & legends born.
You spam "...", "lol", and smilies such as "; p", "^)^",">.>"? You think you're the best and all other ones are stupids or at least less clever than you ? You think your errors are funny, while the other ones are incredibly lame ?
Maybe you've too much ego,or worse, you're a douchebag
Last edited by Troll-Brain; 07-06-2012 at 09:21 PM.
|
|
|
07-07-2012, 12:04 AM
|
#10 (permalink)
|
|
SSJ99999 Pinoy!
Join Date: Mar 2009
Posts: 4,385
|
first thanks and sorry for the '...', it's just my...signature or I'm used to it and for me it doesnt mean
etc, but just like 'nothing' or no harm in putting that :)...
Quote:
|
the event always fire except when the structure is killed/removed, this was tested with the patch 1.26a.
|
that's logical my friend coz how can it fire if there's nothing to cancel/esc?, but
if the unit being trained is removed during training (if it can be removed), maybe
that's another story, gotta test it...
__________________
My Resources:
My Maps
My Systems/Spells
Your ideas tend to result in unnecessary violence so shut the F*** up!
|
|
|
07-07-2012, 05:48 AM
|
#11 (permalink)
|
|
Keep it simple
Spells, Help Zones & JASS Moderator
Join Date: Sep 2009
Posts: 5,581
|
It is not a unit until it is finished training last I checked.
__________________
How to post your triggers on the Hive Workshop.
JPAG - Bettering the cause of readable source code.
|
|
|
07-07-2012, 10:33 AM
|
#12 (permalink)
|
|
cool != useful
Join Date: Apr 2008
Posts: 1,937
|
Quote:
Originally Posted by mckill2009
that's logical my friend coz how can it fire if there's nothing to cancel/esc?, but
if the unit being trained is removed during training (if it can be removed), maybe
that's another story, gotta test it...
|
I've tried to abuse the return bug to get the unit which is being trained (typecast integer to unit), but the unit doesn't seem to be created until the finish train event fire like Bribe said.
Or at least it doesn't follow the usual handle id and when the unit is officially created its id is changed, but meh that doesn't seem credible.
And it's not logical at all, i'm talking about removing, killing the structure which is training the unit.
For example the event spell abort event fire when the caster is killed during the cast (and probably also removed).
__________________
- There are bugs with wc3, but most of time, the bug is between the keyboard and the chair.
- Never believe some warcraft "fact" without a proof, even from an "experienced" user, that's how myths & legends born.
You spam "...", "lol", and smilies such as "; p", "^)^",">.>"? You think you're the best and all other ones are stupids or at least less clever than you ? You think your errors are funny, while the other ones are incredibly lame ?
Maybe you've too much ego,or worse, you're a douchebag
|
|
|
07-08-2012, 12:22 AM
|
#13 (permalink)
|
|
SSJ99999 Pinoy!
Join Date: Mar 2009
Posts: 4,385
|
Quote:
|
...but the unit doesn't seem to be created until the finish train event fire like Bribe said.
|
cancel btw does not get the Trained unit's ID but the trigger unit, I forget to remove the 'trained'
since I just cnp the code from 'trainEnd'...
Jass:
private static method trainCancel takes nothing returns nothing
local unit u = GetTriggerUnit()
//local unit trained = GetTrainedUnit()
local integer ID = GetHandleId(u)
if not chk.boolean[ID] then
set chk.boolean[ID] = true
set chk[ID] = chk[ID] - 1
endif
set u = null
//set trained = null
endmethod
Quote:
And it's not logical at all, i'm talking about removing, killing the structure which is training the unit.
For example the event spell abort event fire when the caster is killed during the cast (and probably also removed).
|
what difference does it make?, coz the structure/unit will be removed from the loop, therefore the instance is recycled...
but IDK if the game will crash when the trained unit dies if the structure is removed/killed so he encounters a null instance
by this
set b = chk.unit[ID]
...
__________________
My Resources:
My Maps
My Systems/Spells
Your ideas tend to result in unnecessary violence so shut the F*** up!
|
|
|
07-08-2012, 06:33 AM
|
#14 (permalink)
|
|
cool != useful
Join Date: Apr 2008
Posts: 1,937
|
No you don't get it, i basically mean that the cancel event should fire when the structure die, i know you handle this case.
However you probably don't handle the case when the structure is removed of the game with RemoveUnit.
__________________
- There are bugs with wc3, but most of time, the bug is between the keyboard and the chair.
- Never believe some warcraft "fact" without a proof, even from an "experienced" user, that's how myths & legends born.
You spam "...", "lol", and smilies such as "; p", "^)^",">.>"? You think you're the best and all other ones are stupids or at least less clever than you ? You think your errors are funny, while the other ones are incredibly lame ?
Maybe you've too much ego,or worse, you're a douchebag
|
|
|
07-10-2012, 09:22 AM
|
#15 (permalink)
|
|
SSJ99999 Pinoy!
Join Date: Mar 2009
Posts: 4,385
|
That I didnt get it, perhaps a map sample would be great...
__________________
My Resources:
My Maps
My Systems/Spells
Your ideas tend to result in unnecessary violence so shut the F*** up!
|
|
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
|
|
|
|
|
|
All times are GMT. The time now is 01:44 AM.
|