HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Reconstruction ability

03-16-2009, 07:49 PM#1
cosmicat
Well, this is pretty much my first real stab at a JASS spell - such as it is. The idea sort of came about through the Custom Race topic, when people were discussing unique ways to harvest resources, build/repair things, etc. Even though I'm supposed to submit a Pandaren race, it got me thinking - a goblin race wouldn't bother repairing a damaged building. They'd just blow it up and make a new one!

However, because of my inexperience in JASS, the "spell" runs into a few problems and is fairly dependent on dummy-casters. Also, the positioning of the functions (in global space) makes it easier to use, but there's probably something else I should be doing with that space (looking at other JASS spells, it looks like I should be able to stick that block of code somewhere else and still be able to get it to work...). So. Suggestions?

And I haven't got a clue about vJASS yet.

The spell actually comes in two forms: the first tries to rebuild the structure from scratch (making it much more authentic, I suppose) while the second simply pauses the building and gives it extremely low health, then heals it over time and unpauses when it's fully healed.

Known issues:
(first method)
- Dummy Builder must be Undead to prevent leaks.
- Building will be destroyed and not replaced if builder is unable to build the structure (including techtree requirements, e.g. Altar of Storms must exist for Fortress to be built).
- Build speed cannot be increased (without making the builder Human and potentially leaking)

(second method)
- Depending on the healing method used, various restrictions apply.
- Looks a little clumsier than the first method

So, um, here's the code:
Expand JASS:
And here's the map...
Attached Files
File type: w3xGoblin Reconstruction.w3x (25.4 KB)
03-18-2009, 07:57 PM#2
cosmicat
Hm, perhaps I should have put [help] in the thread title. Or...something. Anyway, I'd still like to know what I can do to fix some of the problems (if there is a solution), and if it'd look nicer in structs I'll see what I can do about a vJASS version (but if you never complain, I'll never know).
03-21-2009, 07:02 PM#3
cosmicat
I'd really appreciate some sort of feedback. Anyone have a link to a set of "coding standards"? Are there any?
03-21-2009, 08:29 PM#4
Kyrbi0
Sorry, I don't know how to help you (and I haven't been out of the house in order to download :P).
03-22-2009, 03:44 AM#5
BoNe
Collapse JASS:
local unit building = target
What's the point of this? Can't you just use target instead of building?
Collapse JASS:
local player owner = GetOwningPlayer(target)
You only use owner once; instead of owner just use GetOwningPlayer(target).
Collapse JASS:
if not IsUnitType(target, UNIT_TYPE_STRUCTURE) then
        return
    endif
Have this in the function that calls this function instead.
Collapse JASS:
function CreateUnitAtLocSaveLast takes player id, integer unitid, location loc, real face returns unit
    if (unitid == 'ugol') then
        set bj_lastCreatedUnit = CreateBlightedGoldmine(id, GetLocationX(loc), GetLocationY(loc), face)
    else
        set bj_lastCreatedUnit = CreateUnitAtLoc(id, unitid, loc, face)
    endif

    return bj_lastCreatedUnit
endfunction
Because of this,
Collapse JASS:
CreateUnitAtLocSaveLast(owner, DUMMY_UNIT, site, bj_UNIT_FACING)
can become
Collapse JASS:
CreateUnitAtLoc(GetOwningPlayer(target), DUMMY_UNIT, site, bj_UNIT_FACING)
Collapse JASS:
function IssueBuildOrderByIdLocBJ takes unit whichPeon, integer unitId, location loc returns boolean
    if (unitId == 'ugol') then
        return IssueHauntOrderAtLocBJ(whichPeon, loc)
    else
        return IssueBuildOrderById(whichPeon, unitId, GetLocationX(loc), GetLocationY(loc))
    endif
endfunction
Because of this,
Collapse JASS:
call IssueBuildOrderByIdLocBJ(repairman, buildingId, site)
can become
Collapse JASS:
call IssueBuildOrderById(repairman, buildingId, GetLocationX(site), GetLocationY(site))
Collapse JASS:
call PolledWait(2)
Does this have to be exactly 2 seconds? If so, use timers as PolledWait() is very inaccurate.

Collapse JASS:
    if not IsUnitType(repairman, UNIT_TYPE_UNDEAD) then        
        loop
            exitwhen(GetUnitLifePercent(building) > 99.99)
            call PolledWait(0.01)
            exitwhen(IsUnitDeadBJ(building))
        endloop
    endif
Can become
Collapse JASS:
if not IsUnitType(repairman, UNIT_TYPE_UNDEAD) then        
        loop
            exitwhen GetUnitStatePercent(target, UNIT_STATE_LIFE, UNIT_STATE_MAX_LIFE)
            call PolledWait(0.01)
            exitwhen GetUnitState(target, UNIT_STATE_LIFE) <= 0
        endloop
    endif

Collapse JASS:
call ShowUnit(repairman, false)
    call KillUnit(repairman)
Do this instead of RemoveUnit(), last I heard it was buggy.

Collapse JASS:
call RemoveLocation(site)
A must have to add into your script, if left out you would be leaking locations every time the function ran.

Also, why would the builder not being Undead cause leaks?
03-22-2009, 07:36 AM#6
cosmicat
Thank you so much for looking at it and providing such detailed feedback. You definitely deserve +rep, and I wish I could do more...
Quote:
Originally Posted by BoNe
What's the point of this? Can't you just use target instead of building?
Good point. I hadn't known function parameters were always local, so I used an extra variable to be safe. Will fix.
Quote:
Originally Posted by BoNe
You only use owner once; instead of owner just use GetOwningPlayer(target).
Same as above. Thanks.
Quote:
Originally Posted by BoNe
Have this in the function that calls this function instead.
Since the spell itself should only be able to target structures in the first place, it's probably unnecessary anyway. I just put that in there so people don't "break" it by accident. But with proper documentation that really shouldn't happen anyway, so...yeah, I'll just take it out. Thanks for pointing this out.
Quote:
Originally Posted by BoNe
Collapse JASS:
function CreateUnitAtLocSaveLast takes player id, integer unitid, location loc, real face returns unit
    if (unitid == 'ugol') then
        set bj_lastCreatedUnit = CreateBlightedGoldmine(id, GetLocationX(loc), GetLocationY(loc), face)
    else
        set bj_lastCreatedUnit = CreateUnitAtLoc(id, unitid, loc, face)
    endif

    return bj_lastCreatedUnit
endfunction
Because of this, CreateUnitAtLocSaveLast(owner, DUMMY_UNIT, site, bj_UNIT_FACING) can become CreateUnitAtLoc(GetOwningPlayer(target), DUMMY_UNIT, site, bj_UNIT_FACING)
I see. This is inlining, right? I didn't really know how to do it, but I think I get it now that I've seen these examples - you just bypass the stuff you don't need, right?
Quote:
Originally Posted by BoNe
Collapse JASS:
function IssueBuildOrderByIdLocBJ takes unit whichPeon, integer unitId, location loc returns boolean
    if (unitId == 'ugol') then
        return IssueHauntOrderAtLocBJ(whichPeon, loc)
    else
        return IssueBuildOrderById(whichPeon, unitId, GetLocationX(loc), GetLocationY(loc))
    endif
endfunction
Because of this, call IssueBuildOrderByIdLocBJ(repairman, buildingId, site) can become call IssueBuildOrderById(repairman, buildingId, GetLocationX(site), GetLocationY(site))
Should I be doing this with every red (BJ) function I call? Or is it only necessary for the ones that use an "if" in them?
Quote:
Originally Posted by BoNe
Collapse JASS:
call PolledWait(2)
Does this have to be exactly 2 seconds? If so, use timers as PolledWait() is very inaccurate.
Ah, okay. I didn't know that.
Quote:
Originally Posted by BoNe
Collapse JASS:
    if not IsUnitType(repairman, UNIT_TYPE_UNDEAD) then        
        loop
            exitwhen(GetUnitLifePercent(building) > 99.99)
            call PolledWait(0.01)
            exitwhen(IsUnitDeadBJ(building))
        endloop
    endif
Can become
Collapse JASS:
if not IsUnitType(repairman, UNIT_TYPE_UNDEAD) then        
        loop
            exitwhen GetUnitStatePercent(target, UNIT_STATE_LIFE, UNIT_STATE_MAX_LIFE)
            call PolledWait(0.01)
            exitwhen GetUnitState(target, UNIT_STATE_LIFE) <= 0
        endloop
    endif
Polled waits are okay here? Ok.
Quote:
Originally Posted by BoNe
Collapse JASS:
call ShowUnit(repairman, false)
    call KillUnit(repairman)
Do this instead of RemoveUnit(), last I heard it was buggy.
Cool. What's the bug with RemoveUnit()?
Quote:
Originally Posted by BoNe
Collapse JASS:
call RemoveLocation(site)
A must have to add into your script, if left out you would be leaking locations every time the function ran.
Oh, okay. I thought setting it to null would be enough. Thanks.
Quote:
Originally Posted by Bone
Also, why would the builder not being Undead cause leaks?
It wouldn't always leak, but there's a potential "leak" if the building stays damaged for the whole game (never reaching 0 or 100% life). Basically, since an Undead builder "summons" a building, he can be killed as soon as he's created the building. A living builder, though, needs to stay alive while he's building the building, so if he finishes the building and the building is damaged, the trigger never exits and keeps looping endlessly until the building is either killed or repaired. This is, I think, a failry minor concern, since it's not likely the leaks will add up to anything significant. Still, it is a leak, and it would have been nice if there had been a native function for building progress detection.
03-22-2009, 12:59 PM#7
Tide-Arc Ephemera
Quote:
Originally Posted by BoNe
Collapse JASS:
if not IsUnitType(repairman, UNIT_TYPE_UNDEAD) then        
        loop
            exitwhen GetUnitStatePercent(target, UNIT_STATE_LIFE, UNIT_STATE_MAX_LIFE)
            call PolledWait(0.01)
            exitwhen GetUnitState(target, UNIT_STATE_LIFE) <= 0
        endloop
    endif

'the hell? 2 exitwhens? Never seen that before... And I thought polled waits had that strange ~.2 sec minimum anyway.
03-22-2009, 05:52 PM#8
akolyt0r
use IsUnitType(repairman, UNIT_TYPE_UNDEAD)==false...
hmm IsUnitType got some issues ...you shoudl always use "==true" or "==false" with it ..