System Automatic Creep Revival

Furby

Current occupation: News poster
Reaction score
144
i1mgrl.png[

v2.2

2jzbqa.png
v2.2 - 5.14.2010
- Removed some unnecessary nulling​

Older update:
v2.1 - 5.10.2010
- You can now set time of first appear
- Respawn time now has min and max time of respawn​

v2.0 - 5.8.2010
- Removed [MAX_CREEP], using linked list now, thanks to all who helped and forced me to :)
- There's effect on creeps revive now, you can change it in globals​

v1.5 - 5.5.2010
- Fixed "fixed" bug :D
- Now definitely works properly​

v1.4 - 5.3.2010
- Fixed major bug causing system to not work properly​

v1.3 - 4.19.2010
- Now does all stuff in enum function
- MAX_CREEPS increased to 8191, not like you ever going to need that high number
- struct is now not private, could not compile​

v1.2 - 4.18.2010
- Now uses only one global group for all enum calls​

v1.1 - 4.14.2010
- Scope changed to library​

v1.0a - 4.13.2010
- Fixed an error causing system not to compile​

v1.0 - 4.13.2010

- First release​

33o4mpv.png
I remade an old version of creep revival, now using structs, has cleaner code, a way to filter units before storing as creeps.​

dmd7dd.png

6ozti8.png
  • Make new trigger.
  • Rename it to Automatic Creep Revival or whatever you want.
  • Edit -> Convert to custom text.
  • Replace the whole trigger with the code.
  • Edit configurables if needed.
You don't have to do anything else! Just put creeps on map! You don't have to set any variables or call any functions! It will do all job for you!

k1b6tj.png
JASS:
//  |==========================================|
//  |******************************************|
//  |*****    AUTOMATIC CREEP REVIVAL     *****|
//  |***     ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯     ****|
//  |**              by Furby               ***|
//  |*****             v2.2               *****|
//  |******************************************|
//  |            - Requirements -              |
//  |               TimerUtils                 |
//  |                 Table                    |
//  |******************************************|
//  |                Credits:                  |
//  |             - Jesus4Lyf -                |
//  |      telling me to use linked list       |
//  |                                          |
//  | - Viikuna, kingkingyyk3, SerraAvenger -  |
//  |   helping me understand linked lists     |
//  |                                          |
//  |******************************************|
//  |        more info at thehelper.net        |
//  |==========================================|
library AutomaticCreepRevival requires TimerUtils, Table
    
    globals
        private constant real   INIT_SPAWN       = 60. // At what time of game will creeps firstly appear
        private constant real   RESPAWN_TIME_MIN = 30. // Minimal time between death of last creep of camp and reviving
        private constant real   RESPAWN_TIME_MAX = 30. // Maximal time between death of last creep of camp and reviving
        private constant real   BASE_MAXRADIUS   = 700. // Maximum radius of camp
        private constant string REVIVE_EFFECT    = "Abilities\\Spells\\Human\\Polymorph\\PolyMorphDoneGround.mdl" // Path of revive effect
        private constant string REVIVE_ATTACH    = "origin" // Path of attach point
    endglobals
    
    // If this function will return true, unit will be stored as creep if not, unit will be ignored
    private function ValidCreep takes unit whatCreep returns boolean
        return /*
        */GetOwningPlayer(whatCreep)                 == Player(PLAYER_NEUTRAL_AGGRESSIVE) and /*
        */IsUnitType(whatCreep, UNIT_TYPE_STRUCTURE) == false                             and /*
        */IsUnitType(whatCreep, UNIT_TYPE_ANCIENT)   == false                           //and
    endfunction
    
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = = 
    //  DO NOT TOUCH BELOW UNLESS YOU KNOW WHAT'RE YOU DOING!
    // = = = = = = = = = = = = = = = = = = = = = = = = = = = =
    
    globals
        private group ALL = CreateGroup()
        private group G = CreateGroup()
        private CreepCamp CAMP = 0
        private CreepUnit UNIT = 0
    endglobals
    
    struct CreepUnit
        unit    creep      // Actual creep units
        integer creepOwner // Id of the creep's owner
        integer creepType  // Type of the creep (raw code)
        real    creepX     // X position of the creep
        real    creepY     // Y position of the creep
        real    creepAng   // Angle of the creep
        static HandleTable table
        CreepUnit next
    endstruct
    
    struct CreepCamp // Struct instances are basicly creep camps
        CreepUnit first
        
        private static method onRevive takes nothing returns nothing
            local timer t = GetExpiredTimer()
            local thistype this = thistype(GetTimerData(t))
            local CreepUnit mob = this.first
            loop
                exitwhen(mob.next == mob)
                set mob = mob.next
                call ShowUnit(mob.creep, true)
                call DestroyEffect(AddSpecialEffectTarget(REVIVE_EFFECT, mob.creep, REVIVE_ATTACH))
            endloop
            call ReleaseTimer(t)
        endmethod
        
        private static method onDeath takes nothing returns boolean
            local unit dead = GetTriggerUnit()
            local thistype this = thistype(CreepUnit.table[dead])
            local CreepUnit mob = 0
            local boolean startTimer = true
            local timer t
            if this != 0 then
                call CreepUnit.table.flush(dead)
                set mob = this.first
                loop
                    exitwhen(mob.next == mob)
                    set mob = mob.next
                    if mob.creep == dead then
                        set mob.creep = CreateUnit(Player(mob.creepOwner), mob.creepType, mob.creepX, mob.creepY, mob.creepAng)
                        set CreepUnit.table[mob.creep] = this
                        call ShowUnit(mob.creep, false)
                    endif
                    if IsUnitHidden(mob.creep) == false then
                        set startTimer = false
                    endif
                endloop
                if startTimer then
                    set t = NewTimer()
                    call TimerStart(t, GetRandomReal(RESPAWN_TIME_MIN, RESPAWN_TIME_MAX), false, function thistype.onRevive)
                    call SetTimerData(t, this)
                endif
            endif
            set dead = null
            return false
        endmethod
        
        private static method saveCreeps takes nothing returns boolean
            local unit filter = GetFilterUnit()
            local CreepUnit another
            if ValidCreep(filter) and CreepUnit.table.exists(filter) == false then
                set CreepUnit.table[filter] = CAMP
                set another = CreepUnit.create()
                set UNIT.next = another
                set UNIT = another
                set UNIT.creep = filter
                set UNIT.creepOwner = GetPlayerId(GetOwningPlayer(filter))
                set UNIT.creepType = GetUnitTypeId(filter)
                set UNIT.creepX = GetUnitX(filter)
                set UNIT.creepY = GetUnitY(filter)
                set UNIT.creepAng = GetUnitFacing(filter)
                call ShowUnit(UNIT.creep, false)
            endif
            return false
        endmethod
        
        private static method saveCamps takes nothing returns boolean
            local unit filter = GetFilterUnit()
            local real x = GetUnitX(filter)
            local real y = GetUnitY(filter)
            local integer i
            local boolean result = false
            if ValidCreep(filter) and CreepUnit.table.exists(filter) == false then
                set CAMP = thistype.create()
                set UNIT = CreepUnit.create()
                set CAMP.first = UNIT
                call GroupEnumUnitsInRange(G, x, y, BASE_MAXRADIUS, Condition(function thistype.saveCreeps))
                set UNIT.next = UNIT
                set result = true
            elseif CreepUnit.table.exists(filter) then
                set result = true
            endif
            set filter = null
            return result
        endmethod
        
        private static method showUnits takes nothing returns nothing
            call ShowUnit(GetEnumUnit(), true)
        endmethod
        
        private static method firstSpawn takes nothing returns boolean
            call ForGroup(ALL, function thistype.showUnits)
            call DestroyGroup(ALL)
            set ALL = null
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing 
            local trigger t = CreateTrigger()
            set CreepUnit.table = HandleTable.create()
            call GroupEnumUnitsInRect(ALL, bj_mapInitialPlayableArea, Condition(function thistype.saveCamps))
            call TriggerRegisterTimerEvent(t, INIT_SPAWN, false)
            call TriggerAddCondition(t, Condition(function thistype.firstSpawn))
            set t = CreateTrigger()
            call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_DEATH)
            call TriggerAddCondition(t, Condition(function thistype.onDeath))
            call DestroyGroup(G)
            set G = null
        endmethod
    endstruct
endlibrary

10dh2si.png
  • Does it respawn the whole camp of creeps at once?
    - Yes, all units of camp at once.
  • But I want random spawns!
    - Alt + F4
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
JASS:
            if table.exists(filter) then
            endif


What's the need for this? =P

Also, you could move the FirstOfGroup() loop into the filter saveCamp.

And, I am not sure how much of a difference it makes (or if it even makes a difference) but perhaps you should use [ljass]not[/ljass] instead of [ljass]== false[/ljass].

Otherwise, cool. =D
 

Furby

Current occupation: News poster
Reaction score
144
JASS:
            if table.exists(filter) then
            endif


What's the need for this? =P
So it won't store one creep more times. :)

Also, you could move the FirstOfGroup() loop into the filter saveCamp.
I would have to make some other globals variables which would be useless after initialization, this way it's easier.

Otherwise, cool. =D
Thank you. ;)

[ljass]scope AutomaticCreepRevival[/ljass]

Make this a library that uses the requirements
No need. You only make libraries if mapper will need to require your system. But there's no way anyone will require this for any other library. :)
And scope is declared always after libraries, so? :rolleyes:
 

Anachron

New Member
Reaction score
53
No need. You only make libraries if mapper will need to require your system. But there's no way anyone will require this for any other library.
And scope is declared always after libraries, so?
Librarys are thought for systems.
Scopes are thought for spells.

To be even more corret, you are right. scopes are thought for non-required 'librarys', but actually every system could be used by another library, which makes sense.

Just because you don't know a reason to do this doesn't mean you should remove the posability from the users functionality.

About the code itself: Does this detect creep camps automatically?
Does this for example revive creeps only when the whole group is dead, and that after x seconds?
 

Furby

Current occupation: News poster
Reaction score
144
Librarys are thought for systems.
Scopes are thought for spells.

To be even more corret, you are right. scopes are thought for non-required 'librarys', but actually every system could be used by another library, which makes sense.

Just because you don't know a reason to do this doesn't mean you should remove the posability from the users functionality.
Well, okay then I'll change it. I just didn't see reason to make it library if I don't have there any function that can be called. But actually, you are able to make your camps manually if you know how.

About the code itself: Does this detect creep camps automatically?
Does this for example revive creeps only when the whole group is dead, and that after x seconds?
Yes and yes. It's also in faq.
 
Reaction score
91
> No need. You only make libraries if mapper will need to require your system.
You had stated in your first post that it required TimerUtils & Table... :rolleyes: Nevermind, I see you've made it a library now.
Anyway, this is pretty short and useful and I think I'll be using it in a map of mine (due to laziness to code my own ^^).
 

Furby

Current occupation: News poster
Reaction score
144
You had stated in your first post that it required TimerUtils & Table... :rolleyes: Nevermind, I see you've made it a library now.
I meant, if mappers who use your system will set it as a requirement in their maps. Which is no need for this one.

Anyway, this is pretty short and useful and I think I'll be using it in a map of mine (due to laziness to code my own ^^).
That's why I made it. :) You just put it in map and you don't have to store all data manually, I hated it, so I made this. :p
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
private constant integer MAX_CREEPS     = 5 // Maximum number of creeps per camp

This should not be necessary... use linked lists, or something? The size of creep camps should be infinite (well, 8191) and dynamic (only as big as they need to be, using linked-lists for this).

Basically, I think this should work for the case that you set radius to 99999 - causing all creeps to revive on the map when they all die. :)
 

Furby

Current occupation: News poster
Reaction score
144
Nah, that would need just another system. And I didn't read how LinkedList works. :D
 

Viikuna

No Marlo no game.
Reaction score
265
Your Group usage sucks.
Use only one global group for all GroupEnum calls.
 

Viikuna

No Marlo no game.
Reaction score
265
Looks better. Just dont destroy it in Init function like that. You are gonna need it during the game, yo. : D

Also you dont really need that loop thing. You could do that stuff in filter function, because it already goes through all those units. Now you kinda have 2 loops when you only need one.
 

Furby

Current occupation: News poster
Reaction score
144
Just, that you don't need it here. :)

It works with no help.
 

Furby

Current occupation: News poster
Reaction score
144
Version 1.4 released.

Fixed major bug causing creeps to not be initialized properly.

What else before approving? :)
 

Jesus4Lyf

Good Idea™
Reaction score
397
JASS:
struct CreepCamp // Struct instances are basicly creep camps

Private? :thup:
JASS:
unit    array creep     [MAX_CREEPS] // Actual creep units

Does this work?? :confused:

You have MAX_CREEPS set to 8190. I think you seriously need to re-read my last post, before approve. And consider implementing it, or at least asking for help about it or something...

I currently do not believe this system works.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top