• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Solved] How Can I Change the Model of a Building When It Loads/Unloads a Unit?

Status
Not open for further replies.
Level 21
Joined
May 29, 2013
Messages
1,567
I'm making an ability that works just like the Orc Burrow's Battle Stations, but with only one unit per building and the building should have a different model while the unit is in it.
MurlocTower.png

So, how can I change the building's model every time a unit is loaded/unloaded?
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
Sounds familiar... ; )

Dang you, taking all the good ideas before I can get to them... I have something much like this planned for my Dwarven race (STEAM TANKS BRAAAAAH).

~~~

To actually answer your question... Hm. My first thought is Chaos; never used it myself but it seems that people use it a lot (don't even have to worry about hold-over buffs, right?... Wait, does your Murloc mod have to face off against Frost Wyrms/Batriders/Chimaeras?).

I am also learning that, if you can use a custom model (which you are), you can simply add a special attachment point ("sprite first") and then... attach... the guy to it? I think? (It works for the Impale spike & the Cyclone tornado, somehow).

Alternatively (again with a custom model), simply give the tower a series of forms that feature the unit inside (w/o custom animations, see below), and you can even label them whatever (because you can call it by name in the Trigger/Object Editor). So animation tags "murloc1", "murloc2" or perhaps "warrior", "caster", etc.

~

Question: Does the "garrisoned" unit need to move around/attack/react in any way while garrisoned? If he's just "Model-attached" he'll have no animations (as I'm sure you know), but if you use the attachment thing (above) he'll just sit in the stock 'Stand' animation (which might be enough). Otherwise...?
 
Level 21
Joined
May 29, 2013
Messages
1,567
Replace the building model with another one after the unit is been loaded/unloaded.
I tried to replace the building when it loads a unit. The building is replaced, but the unit is instantly unloaded. Also, I don't think there's a unit is unloaded event.
don't even have to worry about hold-over buffs, right?
What do you mean?
Wait, does your Murloc mod have to face off against Frost Wyrms/Batriders/Chimaeras?
Yes, why?
I am also learning that, if you can use a custom model (which you are), you can simply add a special attachment point ("sprite first") and then... attach... the guy to it?
I know, but I don't want to do it like that.
Alternatively (again with a custom model), simply give the tower a series of forms that feature the unit inside (w/o custom animations, see below), and you can even label them whatever (because you can call it by name in the Trigger/Object Editor). So animation tags "murloc1", "murloc2" or perhaps "warrior", "caster", etc.
This is getting off topic, but I'm making a tower that has no attack, but can be upgraded into different defensive towers, just like the Human Scout Tower. The towers will all look the same, but each type of tower will have a different type of Murloc.
Question: Does the "garrisoned" unit need to move around/attack/react in any way while garrisoned? If he's just "Model-attached" he'll have no animations (as I'm sure you know), but if you use the attachment thing (above) he'll just sit in the stock 'Stand' animation (which might be enough). Otherwise...?
The Murloc is not attached, it's a part of the tower's upgrade first form. It turns to face the target it attacks (and has attack and spell animations).
 
Level 21
Joined
May 29, 2013
Messages
1,567
I presume this means you tried Bear Form morphing the tower while a unit was loaded in it?
Bear Form will always cause the building to start playing it's birth animation. Chaos seems to be working (but I'm not sure, since Kyrbi0 said something about buffs). However, all abilities are still a one way transformation.
There is no unload event but there are libraries to detect it.
If JASS is the only way to do this, I might as well give up.:(
 
Last edited:
Level 13
Joined
Mar 24, 2013
Messages
1,105
You could just trigger the whole process.

Unit casts your "load" ability on the target > hide the unit loaded, hide the loading building, create/unhide the new modeled unit.

Unload ability cast > unhide loaded unit, hide/kill the new modeled unit, unhide the original building.

There a few other ways to do this, one of which as pyro said, by using resources that can detect unloading events.
 
Level 21
Joined
May 29, 2013
Messages
1,567
You could just trigger the whole process.
I absolutely suck at making triggers. I barely even know how to use GUI (I actually never made a trigger that was longer than 20 lines) and I don't know any JASS. Most of the triggers I use are just slightly edited triggers that I copied from somewhere.
create the new modeled unit.
Is it even possible to create a new building with a new unit in it and set their hit points to be equal to the previous building's and previous unit's (before they were replaced)? That sounds really complicated.
Unload ability cast
I can detect it like this -> (Issued order) Equal to (Order(standdown)), but the unit can also be unloaded by just clicking it's icon.
 
Level 13
Joined
Mar 24, 2013
Messages
1,105
So I probably should have clarified a lot of things before potentially solving the "wrong" problem, but take a look at what I came up with, we can easily tailor it more towards your needs.

Bear in mind because I don't use the standard Load/Unload abilities here. Instead the abilities are based on Channel. Some of the features of the standard abilities are "lost", but if we want we can likely add them in ourselves.




  • Catalog
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Buildings[1] = Siege Engine 1
      • Set Buildings[2] = Watch Tower 1
      • Set Buildings2[1] = Siege Engine 2
      • Set Buildings2[2] = Watch Tower 2
      • Set MaxTypes = 2
  • Load
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Load
    • Actions
      • Set Load_MaxIndex = (Load_MaxIndex + 1)
      • Set Load_Building[Load_MaxIndex] = (Triggering unit)
      • Set TempPoint = (Position of Load_Building[Load_MaxIndex])
      • Set Load_Unit[Load_MaxIndex] = (Target unit of ability being cast)
      • Unit - Hide Load_Building[Load_MaxIndex]
      • Unit - Hide Load_Unit[Load_MaxIndex]
      • For each (Integer TempInteger) from 1 to MaxTypes, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of Load_Building[Load_MaxIndex]) Equal to Buildings[TempInteger]
            • Then - Actions
              • Unit - Create 1 Buildings2[TempInteger] for (Owner of Load_Building[Load_MaxIndex]) at TempPoint facing (Facing of Load_Building[Load_MaxIndex]) degrees
              • Set Load_NewBuilding[Load_MaxIndex] = (Last created unit)
              • Unit - Set life of Load_NewBuilding[Load_MaxIndex] to (Life of Load_Building[Load_MaxIndex])
              • Selection - Select Load_NewBuilding[Load_MaxIndex] for (Owner of Load_Building[Load_MaxIndex])
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)
  • Unload
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Unload
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempPoint = (Target point of ability being cast)
      • For each (Integer TempInteger) from 1 to Load_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to Load_NewBuilding[TempInteger]
            • Then - Actions
              • Set TempPoint2 = (Position of Load_NewBuilding[TempInteger])
              • Unit - Remove Load_NewBuilding[TempInteger] from the game
              • Unit - Unhide Load_Building[TempInteger]
              • Unit - Unhide Load_Unit[TempInteger]
              • Unit - Make Load_Building[TempInteger] face (Facing of Load_NewBuilding[TempInteger]) over 0.00 seconds
              • Unit - Move Load_Building[TempInteger] instantly to TempPoint2
              • Unit - Move Load_Unit[TempInteger] instantly to TempPoint
              • Unit - Set life of Load_Building[TempInteger] to (Life of Load_NewBuilding[TempInteger])
              • Selection - Select Load_Building[TempInteger] for (Owner of Load_Building[TempInteger])
              • Set Load_Building[TempInteger] = Load_Building[Load_MaxIndex]
              • Set Load_NewBuilding[TempInteger] = Load_NewBuilding[Load_MaxIndex]
              • Set Load_Unit[TempInteger] = Load_Unit[Load_MaxIndex]
              • Set Load_MaxIndex = (Load_MaxIndex - 1)
              • Set TempInteger = (TempInteger - 1)
              • Custom script: call RemoveLocation(udg_TempPoint2)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)
 

Attachments

  • LoadUnload.w3x
    19.1 KB · Views: 48
Level 21
Joined
May 29, 2013
Messages
1,567
So I probably should have clarified a lot of things before potentially solving the "wrong" problem, but take a look at what I came up with, we can easily tailor it more towards your needs.

Bear in mind because I don't use the standard Load/Unload abilities here. Instead the abilities are based on Channel. Some of the features of the standard abilities are "lost", but if we want we can likely add them in ourselves.




  • Catalog
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set Buildings[1] = Siege Engine 1
      • Set Buildings[2] = Watch Tower 1
      • Set Buildings2[1] = Siege Engine 2
      • Set Buildings2[2] = Watch Tower 2
      • Set MaxTypes = 2
  • Load
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Load
    • Actions
      • Set Load_MaxIndex = (Load_MaxIndex + 1)
      • Set Load_Building[Load_MaxIndex] = (Triggering unit)
      • Set TempPoint = (Position of Load_Building[Load_MaxIndex])
      • Set Load_Unit[Load_MaxIndex] = (Target unit of ability being cast)
      • Unit - Hide Load_Building[Load_MaxIndex]
      • Unit - Hide Load_Unit[Load_MaxIndex]
      • For each (Integer TempInteger) from 1 to MaxTypes, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Unit-type of Load_Building[Load_MaxIndex]) Equal to Buildings[TempInteger]
            • Then - Actions
              • Unit - Create 1 Buildings2[TempInteger] for (Owner of Load_Building[Load_MaxIndex]) at TempPoint facing (Facing of Load_Building[Load_MaxIndex]) degrees
              • Set Load_NewBuilding[Load_MaxIndex] = (Last created unit)
              • Unit - Set life of Load_NewBuilding[Load_MaxIndex] to (Life of Load_Building[Load_MaxIndex])
              • Selection - Select Load_NewBuilding[Load_MaxIndex] for (Owner of Load_Building[Load_MaxIndex])
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)
  • Unload
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Unload
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempPoint = (Target point of ability being cast)
      • For each (Integer TempInteger) from 1 to Load_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to Load_NewBuilding[TempInteger]
            • Then - Actions
              • Set TempPoint2 = (Position of Load_NewBuilding[TempInteger])
              • Unit - Remove Load_NewBuilding[TempInteger] from the game
              • Unit - Unhide Load_Building[TempInteger]
              • Unit - Unhide Load_Unit[TempInteger]
              • Unit - Make Load_Building[TempInteger] face (Facing of Load_NewBuilding[TempInteger]) over 0.00 seconds
              • Unit - Move Load_Building[TempInteger] instantly to TempPoint2
              • Unit - Move Load_Unit[TempInteger] instantly to TempPoint
              • Unit - Set life of Load_Building[TempInteger] to (Life of Load_NewBuilding[TempInteger])
              • Selection - Select Load_Building[TempInteger] for (Owner of Load_Building[TempInteger])
              • Set Load_Building[TempInteger] = Load_Building[Load_MaxIndex]
              • Set Load_NewBuilding[TempInteger] = Load_NewBuilding[Load_MaxIndex]
              • Set Load_Unit[TempInteger] = Load_Unit[Load_MaxIndex]
              • Set Load_MaxIndex = (Load_MaxIndex - 1)
              • Set TempInteger = (TempInteger - 1)
              • Custom script: call RemoveLocation(udg_TempPoint2)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)
This looks great, thank you! (+rep) It would be perfect if it could only target a specific type of unit and unload the unit when the building is destroyed.
 
Level 11
Joined
Jun 2, 2004
Messages
849
That tower is a custom model, right? And even if not, it should be easy to export and modify slightly.

No need to replace the unit (unless you want to change stats significantly or something); just give it a dummy ability that adds an attachment graphic. You can add an attachment point to the model where the unit should stand. You'd need separate abilities for each unit who can enter the building, but that's better than separate towers. My way's also potentially scaleable to different types of towers.
 
Level 13
Joined
Mar 24, 2013
Messages
1,105
Easy enough.

We could potentially cut down on some code duplication by combining the unload into a single trigger, but I didn't bother because just copy and pasting was easier lol.

Another thing to keep in mind is, since we're creating a new unit, if someone is casting a channeling spell or even ordered to attack the "previous" building, they will need to be reordered since their target will have vanished.


  • Only Peasants
    • Events
      • Unit - A unit Begins channeling an ability
    • Conditions
      • (Ability being cast) Equal to Load
    • Actions
      • Set TempUnit = (Triggering unit)
      • Set TempUnit2 = (Target unit of ability being cast)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Unit-type of TempUnit2) Not equal to Peasant
        • Then - Actions
          • Unit - Pause TempUnit
          • Unit - Order TempUnit to Stop
          • Unit - Unpause TempUnit
          • Game - Display to (All players) the text: Only peasants can b...
        • Else - Actions
  • Unload On Death
    • Events
      • Unit - A unit Dies
    • Conditions
    • Actions
      • Set TempUnit = (Triggering unit)
      • For each (Integer TempInteger) from 1 to Load_MaxIndex, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TempUnit Equal to Load_NewBuilding[TempInteger]
            • Then - Actions
              • Set TempPoint2 = (Position of Load_NewBuilding[TempInteger])
              • Unit - Unhide Load_Unit[TempInteger]
              • Unit - Unhide Load_Building[TempInteger]
              • Unit - Move Load_Unit[TempInteger] instantly to TempPoint2
              • Unit - Move Load_Building[TempInteger] instantly to TempPoint2
              • Unit - Set life of Load_Building[TempInteger] to (Life of Load_NewBuilding[TempInteger])
              • Unit - Remove Load_NewBuilding[TempInteger] from the game
              • Unit - Make Load_Building[TempInteger] face (Facing of Load_NewBuilding[TempInteger]) over 0.00 seconds
              • Set Load_Building[TempInteger] = Load_Building[Load_MaxIndex]
              • Set Load_NewBuilding[TempInteger] = Load_NewBuilding[Load_MaxIndex]
              • Set Load_Unit[TempInteger] = Load_Unit[Load_MaxIndex]
              • Set Load_MaxIndex = (Load_MaxIndex - 1)
              • Set TempInteger = (TempInteger - 1)
              • Custom script: call RemoveLocation(udg_TempPoint2)
            • Else - Actions
      • Custom script: call RemoveLocation(udg_TempPoint)


Edit: So after adding the unload upon death, I ran into a bizarre scenario where the unloaded unit was simply lost if the building died before the unit was unhidden. It makes no sense because there is no correlation between those two things, as the simulated load/unload are really only just using hides. So to fix it, I needed to reorder the code, but it is no longer a problem, but it doesn't make sense why it was ever a problem tbh.
 

Attachments

  • LoadUnload.w3x
    20.7 KB · Views: 45
Last edited:
Level 21
Joined
May 29, 2013
Messages
1,567
That tower is a custom model, right? And even if not, it should be easy to export and modify slightly.

No need to replace the unit (unless you want to change stats significantly or something); just give it a dummy ability that adds an attachment graphic. You can add an attachment point to the model where the unit should stand. You'd need separate abilities for each unit who can enter the building, but that's better than separate towers. My way's also potentially scaleable to different types of towers.
I made that model (well more like put together). As I said, the Murloc is a part of the tower's upgrade first form. If I made it as an attachment, then it wouldn't turn to face the target it attacks and couldn't play attack and spell animations.
Another thing to keep in mind is, since we're creating a new unit, if someone is casting a channeling spell or even ordered to attack the "previous" building, they will need to be reordered since their target will have vanished.
I realize that, but it's good enough. Thank you very much, I really needed this.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
@pOke: Dang. Nothing cements my knowledge that I have no coding knowledge like trying to decipher a simple spell like this. :<

I was following you up to a point... But where do you get Load_MaxIndex (& the other "Load_" variables)? And what are they set to? Why's the Index 2?

Apparently it works, which is all that matters (gonna have to check that out myself, actually; might be quite useful). Good on ya for helping Hermit out.

~~~

@Hermit: Hm. So in answer to my question, "YES, the loaded unit needs to turn to face attackers (as well as attack/cast with animations)". That makes things harder, but not insurmountable.

Something I was working on might be applicable here. I don't think even my version of this is perfect, but it's a Work In Progress.
Basically I have a spell that allows a Troll to "climb" a tree, becoming an invisible sentry/hunter. I did this by having him 'turn into' an entirely separate custom unit; one that is exactly the same as him but flying & no pathing & no motion (& invisible & such of course). Then, when he's summoned at the target location (a tree), he appears right in/on-top of it (fine-tuning the flying height to match, of course). So now he's in the tree, but as a (flying) unit he still has all his animations, can attack, etc.

So if you hide/replace/morph the Loading unit with a copy of himself except flying/no pathing/motion, create/build/move/place him right inside where the tower is and Presto: a "loaded" unit that is visible & can still attack & cast spells, all with his animations.

Of course, since you appear to have something working this is kind of a moot point (though I think mine might be simpler?...). Glad you got help either way.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
That's... exactly what I said. :<

Except for that there doesn't appear to be a native "Unload" event to catch. There's "Unload All", but you can also click on a unit's portrait to Unload it singly, and that's not... something...

Wait, so there's no hope? What about "unit enters region", checking for a nearby Tower? Wait, rather clunky... Is there a way to get rid of the "click on unit portrait" behavior ('cuz then we can just force them to use Unload All)? Or what about... Dang, how did I solve this? Did I solve this?

"Unit Leaves a Transport"?

//EDIT// - Ok now hold up. @Pyrogasm @pOke , there is totally an "unload event" catchable by the game. It's "Order(unload)". I can't attach the working map file I just (re)-tested it in because of all the SECRETZ, but the triggers are thus:

Code:
Unload1
    Events
        Unit - A unit Is issued an order targeting an object
    Conditions
        (Issued order) Equal to (Order(unload))
    Actions
        Game - Display to (All players) the text: Order(Unload) has b...
        Wait 0.01 seconds
        Unit - Move (Target unit of issued order) instantly to ((Position of (Target unit of issued order)) offset by 1000.00 towards (Facing of (Ordered unit)) degrees)

the first has this crazy long line of documentation where I was testing different things to make it work; half of it doesn't make sense to me but I include it regardless:
removed "kill targeted unit" (doesn't even apply to this Event)
removed "kill triggering unit" (seems like a useless catch-all)
BOTH UNITS STILL DIE (clicker and clickee), so, drum-roll please...
removed "kill ordered unit"...
...AND the unit seems to die, but without dropping to the ground or leaving a corpse. almost like it just gets BALEFIRED out of existence.
~
So, testing with "Set Life to 50%"...
WORKS!
Finally, testing with "move instantly..."...
...DOESNT WORK?!
Seriously.
removed "kill target unit of order" and re-instated "kill ordered unit"...
So "ordered unit" DEFINITELY refers to the unit being ordered (duh) (the Zeppelin)
...
IT WORKS... With a tiny 'Wait' function. I'm not sure yet whether it's truly MUI...


and the 2nd

Code:
UnloadBuilding
    Events
        Unit - A unit Is issued an order targeting an object
    Conditions
        (Issued order) Equal to (Order(unload))
        (Unit-type of (Ordered unit)) Equal to Jungle Pathways v2
    Actions
        Game - Display to (All players) the text: Jungle Order(Unload...
        Wait 0.01 seconds
        Unit - Move (Target unit of issued order) instantly to (Rally-Point of (Ordered unit) as a point)

Now those Waits concern me; I don't know if that messes with MUI/MPI considerations. (but even then, wouldn't a (local) unit variable solve that?)

//EDIT// - Unload All doesn't work with this (couldn't get it to work), so I just removed it from the "transport".
 
Level 21
Joined
May 29, 2013
Messages
1,567
there is totally an "unload event" catchable by the game. It's "Order(unload)".
WOW, DOUBLE SOLVED!
you can also click on a unit's portrait to Unload it singly, and that's not... something
In the case of Orc Burrows, when you click the unit's icon to unload it, the "unload" order is issued.
Unload All doesn't work with this
I didn't test the standard "Unload (All)", but replacing the building (with Chaos) works perfectly when I order the Orc Burrow to Unload All (it's actually called Stand Down).
 
Last edited:
Level 13
Joined
Mar 24, 2013
Messages
1,105
@Kyrbi0

Yeah look here GUI Unit Event v2.2.1.0 this has custom events allowing for loading and unloading detection.

In Hermit's case here I figured by the time you add a system and calibrate it to your needs you probably could make something more directly solving the proposed problem.

Although, maybe that was a bad assumption, idk haha.
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
WOW, DOUBLE SOLVED!
Lol, I try. xD

Hermit said:
In the case of Orc Burrows, when you click the unit's icon to unload it, the "unload" order is issued.
...Yeah... That's what I said. That there is a catchable "unload" order, and it's "unload", and it happens when you click the unit portrait.

Hermit said:
I didn't test the standard "Unload (All)", but replacing the building (with Chaos) works perfectly when I order the Orc Burrow to Unload All (it's actually called Stand Down).
Huh, not bad. So you can just catch Order(Stand Down)? I suppose that gives added functionality.

@Kyrbi0

Yeah look here GUI Unit Event v2.2.1.0 this has custom events allowing for loading and unloading detection.

In Hermit's case here I figured by the time you add a system and calibrate it to your needs you probably could make something more directly solving the proposed problem.

Although, maybe that was a bad assumption, idk haha.
I don't get it. Yeah there are systems for it (as we talked about at the beginning), but my mention of you was in a post highlighted the (re)discovery of an "Unload" order, which was previously thought to not exist.
 
Level 39
Joined
Feb 27, 2007
Messages
5,010
I was just parroting information because I'd seen Bribe's Unload event system passed around here a few times with the caveat of "there's no event for this". You can get both the unloaded unit and unloading unit with the "unload" order? Why did you throw those waits in there?
 

Kyrbi0

Arena Moderator
Level 45
Joined
Jul 29, 2008
Messages
9,501
I was just parroting information because I'd seen Bribe's Unload event system passed around here a few times with the caveat of "there's no event for this".
Welp, just goes to show I'm the brains of this operation. ;P

Pyrogasm said:
You can get both the unloaded unit and unloading unit with the "unload" order? Why did you throw those waits in there?
So if you read the "documentation" (big quotes on that one)... It should be 100% unclear as to what's going on. xD

No but really, it claims that "Ordered Unit" is the Loader, while "Target Unit of Issued Order" is the Loadee.

The Waits are, (again, going off of a years-old map) "necessary to make it work". I have no idea why (though it vaguely reminds me of your issue with the multi-target cast spell & frame-rate issues & such). Does that cause problems (been a while)?
 
Status
Not open for further replies.
Top