11/23/2010 - Added sample map. Removed the triggers for brevity and so I don't have to maintain them in two different spots.
11/23/2010 - The ally interact ability needs to set the uncommandable flag on the unit, and the detector needs to require uncommandable units. Otherwise, multiple enemy buildings can be seen. Changes made to behaviors section only.
11/22/2010 - Greatly improved invisibility done through detection. The solution section contains a new synopsis of these changes. Changes have been made to the behaviors and units sections, as well as the action definition "Create Fake Building". The triggers "Select Shop", "Find Fake Buildings" and the constant "Fake Building Check Radius" have been dropped. Added triggers "Sync Energy" and "Share Vision". This new solution solves several of the remaining problems, which we listed in the conclusion section. These were dropped.
The Problem
The ability type "Interact" is used to allow computer controlled building to sell items, units, upgrades, or whatever to all players. It's a great ability that allows you to do a great number of things with very little work. The problem is, this ability only works with neutral units. If the unit is anything other than neutral, you'll receive a message "cannot spend another player's resources". If you need the unit to be allied to certain players, this is a show stopper.
Some people have gotten around this by changing control of the building to the player who's interacting with it. This solution would not work for me, because I needed multiple people to be able to interact with the building at once. I also needed the building to act like an allied building in every way. I needed it to be destructible and say "our allies base is under attack".
On the finer details side of things, you can't see the queue on a building with interact, nor does it work with warp gates. The units pretty much have to come out instantly, or the player is confused. The queue is shared for each player, making it even less useful. There's also one rally point per building. Ability interact also doesn't tell the player that his unit is too far away; again, leading to confusion. I could probably live without most of those things, but I ended up finding ways around all of them.
The Path
A lot went into find the solution. I'm not going to bore you with the gory details, but a lot of the people in IRC helped me through this, and in the end I think the solution is very elegant. It's also not much code, which is great. I spent a great deal more time finding the solution and theorizing in IRC than I actually did programming anything.
Once I worked through all of that, I thought I should share my solution with the community. I know this is a common problem, and we are short on solutions. Feel free to use mine, and let me know if you find any better ways of doing it.
The Solution
So the way everything ended up working was this: I create a new "invisible" unit on top of the real unit. I do this once for every player I want to be able to interact with my shop building. Each copy is owned by the player that can interact with it. So they actually own it, and can interact with it normally. The clones are invulnerable, so that units don't attack them, but their life (and shields) are linked to the real building.
The invisible units are handled via detection. The units themselves are set to cloaked and buried, and detectors are used to give vision to the correct players. The default detectors need to be modified so that you can't see your allies fake buildings. All units in the game need to be given a behavior so that they can see the enemy buildings. Normal shared vision can no longer be used; vision must be shared on a unit-by-unit basis, which can be done when the unit is created.
A behavior with a validator can tell if the player's hero unit is within a certain radius. The validator disables the behavior if there's no heroic unit within the speicfied radius. A requirement on the train ability checks for the behavior, and provides a nice message "Hero character must be within range". This works very nicely for the hero requirement, and allows the building to be hoykeyed, and the hotkey is retained but it can't be used out of range.
Finally, a simple trigger syncs the health and shields of the real buildings with the fake ones. Since I use some energy-based abilities, and wanted allies to share energy pools, I synced their energies with another trigger.
This solution meets all of my requirements and then some. Seperate buildings for each units means seperate queues/cooldowns and rally points. It seems a little weird, but it's really quite elegant in practice.
The Data
Behaviors
You'll need 3 behaviors, all buffs. I'm a big fan of editor prefixes (use them!), so I gave all of them the editor prefix "Building -". The behavior names I used were:
Building - Ally Interact
Building - Fake Building
Building - Hero In Range
So go to the behaviors tab, Add Object..., and give it he name "Ally Interact". Change the behavior type to "Buff" and leave everything else as defaults. Hit OK. Change "Editor - Editor Prefix" to building. Repeat these steps for the other two items on the list above.
The behavior "Ally Interact" requires a slight modification. Under Behaviors - Modification, in the Behavior tab, near the bottom, find State Flags. Set Uncommandable to enabled. This behavior will be removed from the clones, but the uncommandable flag will help our detection later.
You may want to check the hidden flag (Stats - Flags) for all of these behaviors.
We also need to modify a few behaviors that already exist. They are "Detector (10)", "Detector (11)", and "Detector (12)". For each of these behaviors, double click on Behavior - Modification. In the Unit tab, under Detect Filters, uncheck "Ally" and "Player". We no longer want normal detectors to detect allied and player units. Instead, we will be revealing these units via shared vision. I believe all of the detectors use "Detector (11)", but it can't hurt to hit the other two as well.
Finally, duplicate "Detector (11)." I called mine "Detector (Ambient)". Under Behavior - Modification then Detect Filters, set "Buried", "Cloaked" , "Structure", and "Uncommandable" all to "Required". Leave "Ally" and "Player" unchecked. Set the Radius to 20. This will be the behavior we give to all normal units, that will allow them to see these enemy buildings.
Validators
Jump to the validators tab and create a new object. I called mine "Hero in Range." Set the validator type should be "Enumerate Area". Leave everything else at default and hit OK. I then changed the editor prefix to "Building -".
This validator will return false if the criteria is met, and we actually want it to return true to disable our behavior. So we need to work a little backwards. We want to set it so that the criteria is that the hero is in range (thus the name). When the criteria are met, it returns false and doesn't disable the behavior. It's confusing, I know, but it's the way it works.
So click on Search - Areas and click the green X to add an area. Arc should be 360 already. Set Compare to "Greater Than", and Count to 0. Set Radius to whatever radius you want to use. I used 20 because I wanted a little room to move for my units. You may choose something different.
Close the dialog by hitting OK.
Set Target - Location + to "Caster Unit". Set Validator - Compare to "Greater than". I don't know why you have to do it again there, but you do. Finally, set your Search - Search Filters. I set Heroic to "Required", and unchecked the boxes next to Ally, Enemy, and Neutral. Having only Player checked means it will only look for heroic units owner by the owner of the shop. Since each player has his/her own shop, this works perfectly.
The validator is complete. Go back to the behaviors tab, and find "Behavior - Hero In Range". Set the Behavior - Validators (Disable) to the validator you just created.
Requirements
The requirement does the real work, preventing the player from buying when the hero unit is out of range. Fortunately, it's also fairly simple. Create a new requirement. I called mine "Hero In Range" (for consistancy). There's only one kind of requirement, so leave everything default and click OK. I then set the editor prefix to "Building -" (again).
Double click next to Requirements +, and then right click on the Use node, and click Add Requirement Node. Change the Type to "Count Behavior". Change the Alias to our behavior - "Building - Hero in Range". The State should be "Completed at Unit". Finally, set the Tooltip to "Hero character must be within range", or whatever you want it to say. Leave the Show node blank.
So now our requirement expects the building to have our behavior, otherwise we can't use whatever ability the requirement is attached to. The show node is blank, so it will show the ability no matter what, which is the behavior you expect. We also set the tooltip that will show up when the ability is greyed out, which is just plain good user interface.
One last note about requirements: you can only use one requirement per ability (at least with train abilities). If you're using an ability that already has a requirement, and you want to keep it, or if you want to use another ability, you'll need to combine the two requirements. Duplicate the pre-existing requirement, and add the same requirement we just set up to that requirement. It will now have both requirements.
Abilities
For the purposes of this tutorial, I will assume your ability already exists. It's most likely a train or upgrade ability. Either you've built it already, or you're using a pre-existing ability. Either way, I'm not going to go over the bazillions of ways an ability can be set up. If it doesn't exist already, stop now and make it.
If you need your ability for something else (like if you're going to make normal units of the same type), then duplicate the ability. If there are any actors, duplicate those with it. If you don't need to use the ability for anything else, you can just edit it as-is.
Both the ability types train and research have a section called Ability - Info. Double-click it. For each ability in this list, you need to add the requirement "Building - Hero In Range" to it. As I said before, if there's already a requirement that you want to use, you'll need to combine it with the hero in range requirement and use the combined requirement instead.
That's all you need to do for abilities.
Units
Finally, we get to our shop. Find whatever unit you're using as a shop, and add the following behaviors: "Building - Ally Interact" and "Building - Hero in Range". If you duplicated the ability, double click next to Ability - Abilities + and swap the old one for the duplicate. Make sure the command card buttons have the new ability as well.
Under Stats - Flags, check "Buried" and "Cloaked" for your shop. Don't worry, vision will be handled through detection.
Now, the semi-tedious part is applying the behavior "Detector (Ambient)" to every non-detector unit that will be in your game. Without this, the enemy shops simply won't show up at all. Make sure you get all of your units.
The rest of the work is done in triggers.
The Triggers
All of the code is located in the sample map. It's really only a few triggers, and they're really quite simple. I've also commented them well. I encourage you to take a look and see what they do, but the premise is pretty simple:
Initialize Fake Units [Action Definition] needs to be called at map initialization. It creates the duplicates of all the buildings on the map.
Find Fake Buildsings [Function] locates the duplicate building for a specific player.
Create Fake Building [Action Definition] creates a single fake building. It is called multiple times by initialization.
Sync Health [Trigger] and Sync Energy [Trigger] do exactly what they say they do. They are very short.
Share Vision [Trigger] shares vision of newly created units with their allies. This function would be disabled if shared vision isn't used. It is not used on the sample map, because of the strange alliances.
The Conclusion
If everything went properly, you should have yourself some really nice-looking allied shops, that feel just like regular allied buildings. There are a few small exceptions:
Pylons
Protoss buildings require power. We all know this. The problem is that the fake buildings don't have this power. There are a couple ways around this: First, You could just remove the power restriction. This wouldn't work in my game, but it may be fine in another type of game.
What did work in my game was just giving the behavior "Building - Ally Interact" to Pylons as well. Pylons don't need "Hero in Range", becase they don't have abilities. The ally interact ability causes clones to be created, which will provide power to the cloned buildings. Since the healths are synced, if the pylon is destroyed, neither building will be powered.
There is, however, some weirdness if you allow the player to build pylons. He can power the building for himself without powering it for the computer. I'm going to overcome this by disallowing building in near the computer's base. It could also be overcome by cloning the pylon back to the computer player somehow, then they would truly share power matrices. This could be done fairly easily in a trigger.
There's also the issue of supply. In my game, I don't use pylons for supply in my game, so I had no problem setting Stats - Supplies to 0 for my Pylons. If that doesn't work for you, you might need to add a behavior that removes the supply from the Pylon. I don't know of another way to remove supply from a unit in a trigger. You'd probably have to specifically check for unit type Pylon in the "Initialize Fake Buildings" action, and apply the behavior if true.
Shared Vision
The method listed above requires that vision be shared (through triggers) to allied players. If we didn't do this, players would never be able to see allied cloaked units.
I don't understand the advantage of using this over the regular data interact ability?
Would you mind clarifying?
You can use creative target filters and buff applications to ensure that, while a neutral building remains neutral, it will still only sell items to one team.
I don't understand the advantage of using this over the regular data interact ability?
Would you mind clarifying?
You can use creative target filters and buff applications to ensure that, while a neutral building remains neutral, it will still only sell items to one team.
All of the differences are listed in the section "the problem". I needed it to work with more than one player at a time - simulataneously. I needed warp gates to work. I got a few extra benefits as well, like individual queues/cooldowns. Believe me, I wouldn't have gone to all this trouble if the interact ability did what I needed it to.
Even if I could find a data solution, I've come to really like the individual queues that are actual visible. I don't think I'd use a data solution that didn't offer this functionability as well.
Well the differences in "the problem" section can all be worked around using data.
Individual cooldowns can't be though as far as I know.
A great deal of what I did is done in data. Most of the code I posted above are comments. There's really only about 20 lines of code. Even if it could be done in data, I haven't found a way and that solution isn't posted anywhere. I came up with a solution and I wanted to share it with people who might want to use it. It feels like you're trolling. You're just saying that it can be done, but not offering any actual solutions. By contrast, I offer an actual solution.
I've been a long way down that road, tried a lot of things, and asked a lot of people. I'm not nearly as convinced as you are that it actually can be done in data. However you think it could be done in data, I've probably already tried.
Saying "it can be done in data" is a lot different than spending hours building a tutorial to try and help people. There isn't a good solution out there, so I shared mine. If you have alternatives, help people out and post them. Otherwise, you have no right to try and take this away from me or any one else.
Also, the difference is minimal if at all. My triggers were built with performance in mind. They do little, if anything, more than what a data solution would do. The game still needs to scan objects and check conditions. It just does that in triggers instead of data in a few cases. My triggers were designed to only fire when they need to, and quickly dismiss if the conditions aren't meant. How much performance can that really take? There are no periodic triggers.
The other problem with the data editor is that a lot of times it requires a great deal of redundant work. Even setting up the requirements for this solution is quite redundant, for example. It's likely that any solution you offer would require several objects for each specific type of unit. Since I wanted to use my solution on every type of unit producing structure in the game, I want to avoid large amounts of redundant work. I still kept the redundant work on the requirements because that's what worked best. Keep in mind though, redundant work means redundant changes later down the road, which introduces the possibility of error. From a programmer's perspective, this is very bad.
The one problem with this solution, which we tried to solve yesterday on IRC, is that the real per-player selectable buildings aren't properly be hidden behind the dummy building (which is the visual representation of the building and takes damage). However, now that I noticed you did the damage sharing using triggers, I think my way of showing only one building per player or player group will actually work with this. You'll actually use the same number of buildings and you won't need your Selection trigger at all (removing the selection lag, wooo).
The problem now is that you'd need to share its vision with its enemies when you want them to see it. :( However, I think you could work around this by setting its sight radius to 0 and only sharing its vision when an enemy unit is in its own vision range with the building... Uh, that part sounds a bit tricky. I'll post this solution anyway since some (especially co-op) maps might not care that the building can be seen by enemies all the time.
So, instead of using a "dummy building", just place one visible, damageable building at the same spot for each player who can buy stuff from it (owned by that player), and one for the enemies (or other players) who can't buy stuff from it (owned by an ally of the players who can buy stuff from it). Check the "Buried", "Cloaked", and "Undetectable" flags for the building in data editor (Buried removes the distort effect from Cloaked, Cloaked makes it invisible to others and Undetectable makes it not detectable by units with Detector). You might also be able to use your "Building - Ally Interact" behavior to enable those flags if you want.
Make none of the players share vision with each other, and if you want to share the vision of some other units, do that manually using the "Share vision of unit" action first at map initialization for all preplaced units and then every time a unit is trained/constructured. Make the extra building owned by some ally player, and share its vision with all enemy players (otherwise they wouldn't see it at all).
Lastly, make your damage sharing trigger share the damage with each of those buildings whenever any of them takes damage.
In conclusion, you have:
One building for each player who can buy stuff from it, owned by and visible only to that player, sharing damage to all the other buildings at the spot.
One building for all players who can't buy stuff from it (enemies), owned by an ally player of the players who can buy stuff from it, visible only to the enemies, and sharing damage to all the other buildings at the spot.
This is still very hacky and non-perfect so if anyone has any ideas, do share!
Some great suggestions, a1win, that ended up bearing some fruit. I ended up going away from the "undetectable" flag, and instead using detection to reveal units. It's a lot less "hacky" than trying to reveal units manually. The purpose of detection is to reveal units, it just needed a few tweaks.
The changes are posted in the original post. The changelog at the beginning itemizes these changes.
why dont you use actors that make the hidden units invisible?
I dont see the point of all this vision stuff. I also dont understand why you need a gateway that all the players from a team can build from and still have the building destructable.
Maybe in certain circumstances.
I guess good job for getting to a point in your own map where you got it to work.
From reading though your wall of text, I couldnt really tell what your soloutions were actually a soloution to.
I have made some of my own hero shops. What I do Is put a building for each player on top of eachother and set the actor for it so that the actor is only visible to the player that owns the building.... You could possibly then link the buildings together.
can we get a video or a screenshot of what this looks like in game? a video would be better. This sounds like exactly what I need but I just want to make sure before running head first and finding its doesn't quite do what I want
My situation is fairly unique, sure, but it's also fairly common in that I needed to go outside the bounds of what Ability - Interact could do. I figured detailing my plight might help others who are going down the same road. Not everyone is going to have the same requirements, but the need to extend the normal capabilities is a common requirement. The "stacking buildings on top of one another" seems to be a fairly common solution, but no one previous has really detailed how this could be done. Having overcome this goal with some pretty steep requirements, I figured I'd offer my solution.
I'd be interested in hearing how you overcame your problem with actors. I did a lot of toying with actors in building my solution, but didn't have a lot of luck. The detection solution I came up with just today. It sounds complicated, but it's really not. Detection has some pretty powerful filters, so I abused them a little.
It is a wall of text, isn't it? I'm afraid to add screenshots because that will make it even longer. I'll post a sample map soon, so you can see how the interaction works. Perhaps I'll remove all the code and let the code in the sample speak for itself (with all the comments).
Rollback Post to RevisionRollBack
Pocket Warriors - A pokemon-style game with SC2 units and full banking. New demo coming soon!
I'd also like to know how to make a unit actor only show the unit to its owner (or some other player). It annoys me when people reply with "why don't you just do X" without explaining how to actually do X when they can clearly see that the other person doesn't know how to do X, since otherwise he'd have done so in the first place. So please, everyone, less trolling, more sharing your ideas with those who want to learn.
I'd also like to know how to make a unit actor only show the unit to its
owner (or some other player). It annoys me when people reply with "why
don't you just do X" without explaining how to actually do X when they
can clearly see that the other person doesn't know how to do X, since
otherwise he'd have done so in the first place. So please, everyone,
less trolling, more sharing your ideas with those who want to learn.
There are properties on unit actors that set who they are visible too.
Rollback Post to RevisionRollBack
Skype
KageNinpo = SN
My Libraries
DialogLeaderboard & TeamSort
My Projects
SPACEWAR Tribute
Infinite TD
Do you mean Actor - Filters? It has flags for Ally, Enemy, Neutral, and Self, but they are all disabled by default, and enabling some of them doesn't make the actor invisible to the others. So it doesn't work. Is there some other property that does what you're saying? Have you actually tried that it works or are you just saying it because it looks like it can be done?
There are properties on unit actors that set who they are visible too.
Are you being intentionally vague? Do you think you could be a little more specific?
Even if this is the case, unless you can set these properties in triggers I don't see it being much use past a few buildings, since you'd need a seperate actor for the players and the enemies for each building. If such a thing were all data, it wouldn't scale well to lots of buildings. But, since you can't seem to tell me how to do this, I can't say for sure...
Herein lies the problem with this scenario. Everyone seems to be saying "you can do it way", or "I did it this way", but there's a decided lack of concrete information. So at this point I'm going to have to call malarkey on any recommendations that aren't backed with specific information. If I can't test it to see if it does in fact work, then it doesn't even exist.
Rollback Post to RevisionRollBack
Pocket Warriors - A pokemon-style game with SC2 units and full banking. New demo coming soon!
Umm... Specific as go look at unit actors and look at the visibility setting of the actor in question? I dont see that as being all that complicated.
Specific as in which frickin field, buddy? They have names, you know. Because I don't see it. Search for "visibility" on an actor object and you won't see it either. The only other option is "Actor - Flags", which we tried, and it doesn't work.
Unless you can give me a specific field name, the option doesn't exist.
Specific (adj): specifying, explicit, or definite.
He probably was referring to the field Filter, which can filter actors for specific players. Unfortunately, this field seems to have no effect for unit actors.
Well Im sorry I dont have an exact field name for you. Ill have to take a look at my map when I get home. I havent looked at that one for awhile.
Pretty sure I had it hiding the model from players who didnt own the unit. Ill get back to you after I open up my map later tonight.
I'm sorry to be curt with you, it's just that I've chased a lot of wild geese and been given a lot of hollow suggestions. I want to make sure you know, I am open to suggestion, and I am still looking for a "more perfect" solution. However, I need something concrete to go on. Otherwise, what I have works. Frankly, it actually works pretty well.
--
I've attached a sample map. I think it gives a really good demonstration of how everything works. It's actually set up for two players if you can get anyone else in on it. Having two players demonstrates it the best.
Rollback Post to RevisionRollBack
Pocket Warriors - A pokemon-style game with SC2 units and full banking. New demo coming soon!
To post a comment, please login or register a new account.
Advanced Building Interaction
Sample map available at bottom of post.
Changelog
The Problem
The ability type "Interact" is used to allow computer controlled building to sell items, units, upgrades, or whatever to all players. It's a great ability that allows you to do a great number of things with very little work. The problem is, this ability only works with neutral units. If the unit is anything other than neutral, you'll receive a message "cannot spend another player's resources". If you need the unit to be allied to certain players, this is a show stopper.
Some people have gotten around this by changing control of the building to the player who's interacting with it. This solution would not work for me, because I needed multiple people to be able to interact with the building at once. I also needed the building to act like an allied building in every way. I needed it to be destructible and say "our allies base is under attack".
On the finer details side of things, you can't see the queue on a building with interact, nor does it work with warp gates. The units pretty much have to come out instantly, or the player is confused. The queue is shared for each player, making it even less useful. There's also one rally point per building. Ability interact also doesn't tell the player that his unit is too far away; again, leading to confusion. I could probably live without most of those things, but I ended up finding ways around all of them.
The Path
A lot went into find the solution. I'm not going to bore you with the gory details, but a lot of the people in IRC helped me through this, and in the end I think the solution is very elegant. It's also not much code, which is great. I spent a great deal more time finding the solution and theorizing in IRC than I actually did programming anything.
Once I worked through all of that, I thought I should share my solution with the community. I know this is a common problem, and we are short on solutions. Feel free to use mine, and let me know if you find any better ways of doing it.
The Solution
So the way everything ended up working was this: I create a new "invisible" unit on top of the real unit. I do this once for every player I want to be able to interact with my shop building. Each copy is owned by the player that can interact with it. So they actually own it, and can interact with it normally. The clones are invulnerable, so that units don't attack them, but their life (and shields) are linked to the real building.
The invisible units are handled via detection. The units themselves are set to cloaked and buried, and detectors are used to give vision to the correct players. The default detectors need to be modified so that you can't see your allies fake buildings. All units in the game need to be given a behavior so that they can see the enemy buildings. Normal shared vision can no longer be used; vision must be shared on a unit-by-unit basis, which can be done when the unit is created.
A behavior with a validator can tell if the player's hero unit is within a certain radius. The validator disables the behavior if there's no heroic unit within the speicfied radius. A requirement on the train ability checks for the behavior, and provides a nice message "Hero character must be within range". This works very nicely for the hero requirement, and allows the building to be hoykeyed, and the hotkey is retained but it can't be used out of range.
Finally, a simple trigger syncs the health and shields of the real buildings with the fake ones. Since I use some energy-based abilities, and wanted allies to share energy pools, I synced their energies with another trigger.
This solution meets all of my requirements and then some. Seperate buildings for each units means seperate queues/cooldowns and rally points. It seems a little weird, but it's really quite elegant in practice.
The Data
Behaviors
You'll need 3 behaviors, all buffs. I'm a big fan of editor prefixes (use them!), so I gave all of them the editor prefix "Building -". The behavior names I used were:
So go to the behaviors tab, Add Object..., and give it he name "Ally Interact". Change the behavior type to "Buff" and leave everything else as defaults. Hit OK. Change "Editor - Editor Prefix" to building. Repeat these steps for the other two items on the list above.
The behavior "Ally Interact" requires a slight modification. Under Behaviors - Modification, in the Behavior tab, near the bottom, find State Flags. Set Uncommandable to enabled. This behavior will be removed from the clones, but the uncommandable flag will help our detection later.
You may want to check the hidden flag (Stats - Flags) for all of these behaviors.
We also need to modify a few behaviors that already exist. They are "Detector (10)", "Detector (11)", and "Detector (12)". For each of these behaviors, double click on Behavior - Modification. In the Unit tab, under Detect Filters, uncheck "Ally" and "Player". We no longer want normal detectors to detect allied and player units. Instead, we will be revealing these units via shared vision. I believe all of the detectors use "Detector (11)", but it can't hurt to hit the other two as well.
Finally, duplicate "Detector (11)." I called mine "Detector (Ambient)". Under Behavior - Modification then Detect Filters, set "Buried", "Cloaked" , "Structure", and "Uncommandable" all to "Required". Leave "Ally" and "Player" unchecked. Set the Radius to 20. This will be the behavior we give to all normal units, that will allow them to see these enemy buildings.
Validators
Jump to the validators tab and create a new object. I called mine "Hero in Range." Set the validator type should be "Enumerate Area". Leave everything else at default and hit OK. I then changed the editor prefix to "Building -".
This validator will return false if the criteria is met, and we actually want it to return true to disable our behavior. So we need to work a little backwards. We want to set it so that the criteria is that the hero is in range (thus the name). When the criteria are met, it returns false and doesn't disable the behavior. It's confusing, I know, but it's the way it works.
So click on Search - Areas and click the green X to add an area. Arc should be 360 already. Set Compare to "Greater Than", and Count to 0. Set Radius to whatever radius you want to use. I used 20 because I wanted a little room to move for my units. You may choose something different. Close the dialog by hitting OK.
Set Target - Location + to "Caster Unit". Set Validator - Compare to "Greater than". I don't know why you have to do it again there, but you do. Finally, set your Search - Search Filters. I set Heroic to "Required", and unchecked the boxes next to Ally, Enemy, and Neutral. Having only Player checked means it will only look for heroic units owner by the owner of the shop. Since each player has his/her own shop, this works perfectly.
The validator is complete. Go back to the behaviors tab, and find "Behavior - Hero In Range". Set the Behavior - Validators (Disable) to the validator you just created.
Requirements
The requirement does the real work, preventing the player from buying when the hero unit is out of range. Fortunately, it's also fairly simple. Create a new requirement. I called mine "Hero In Range" (for consistancy). There's only one kind of requirement, so leave everything default and click OK. I then set the editor prefix to "Building -" (again).
Double click next to Requirements +, and then right click on the Use node, and click Add Requirement Node. Change the Type to "Count Behavior". Change the Alias to our behavior - "Building - Hero in Range". The State should be "Completed at Unit". Finally, set the Tooltip to "Hero character must be within range", or whatever you want it to say. Leave the Show node blank.
So now our requirement expects the building to have our behavior, otherwise we can't use whatever ability the requirement is attached to. The show node is blank, so it will show the ability no matter what, which is the behavior you expect. We also set the tooltip that will show up when the ability is greyed out, which is just plain good user interface.
One last note about requirements: you can only use one requirement per ability (at least with train abilities). If you're using an ability that already has a requirement, and you want to keep it, or if you want to use another ability, you'll need to combine the two requirements. Duplicate the pre-existing requirement, and add the same requirement we just set up to that requirement. It will now have both requirements.
Abilities
For the purposes of this tutorial, I will assume your ability already exists. It's most likely a train or upgrade ability. Either you've built it already, or you're using a pre-existing ability. Either way, I'm not going to go over the bazillions of ways an ability can be set up. If it doesn't exist already, stop now and make it.
If you need your ability for something else (like if you're going to make normal units of the same type), then duplicate the ability. If there are any actors, duplicate those with it. If you don't need to use the ability for anything else, you can just edit it as-is.
Both the ability types train and research have a section called Ability - Info. Double-click it. For each ability in this list, you need to add the requirement "Building - Hero In Range" to it. As I said before, if there's already a requirement that you want to use, you'll need to combine it with the hero in range requirement and use the combined requirement instead.
That's all you need to do for abilities.
Units
Finally, we get to our shop. Find whatever unit you're using as a shop, and add the following behaviors: "Building - Ally Interact" and "Building - Hero in Range". If you duplicated the ability, double click next to Ability - Abilities + and swap the old one for the duplicate. Make sure the command card buttons have the new ability as well.
Under Stats - Flags, check "Buried" and "Cloaked" for your shop. Don't worry, vision will be handled through detection.
Now, the semi-tedious part is applying the behavior "Detector (Ambient)" to every non-detector unit that will be in your game. Without this, the enemy shops simply won't show up at all. Make sure you get all of your units.
The rest of the work is done in triggers.
The Triggers
All of the code is located in the sample map. It's really only a few triggers, and they're really quite simple. I've also commented them well. I encourage you to take a look and see what they do, but the premise is pretty simple:
The Conclusion
If everything went properly, you should have yourself some really nice-looking allied shops, that feel just like regular allied buildings. There are a few small exceptions:
Pylons
Protoss buildings require power. We all know this. The problem is that the fake buildings don't have this power. There are a couple ways around this: First, You could just remove the power restriction. This wouldn't work in my game, but it may be fine in another type of game.
What did work in my game was just giving the behavior "Building - Ally Interact" to Pylons as well. Pylons don't need "Hero in Range", becase they don't have abilities. The ally interact ability causes clones to be created, which will provide power to the cloned buildings. Since the healths are synced, if the pylon is destroyed, neither building will be powered.
There is, however, some weirdness if you allow the player to build pylons. He can power the building for himself without powering it for the computer. I'm going to overcome this by disallowing building in near the computer's base. It could also be overcome by cloning the pylon back to the computer player somehow, then they would truly share power matrices. This could be done fairly easily in a trigger.
There's also the issue of supply. In my game, I don't use pylons for supply in my game, so I had no problem setting Stats - Supplies to 0 for my Pylons. If that doesn't work for you, you might need to add a behavior that removes the supply from the Pylon. I don't know of another way to remove supply from a unit in a trigger. You'd probably have to specifically check for unit type Pylon in the "Initialize Fake Buildings" action, and apply the behavior if true.
Shared Vision
The method listed above requires that vision be shared (through triggers) to allied players. If we didn't do this, players would never be able to see allied cloaked units.
I don't understand the advantage of using this over the regular data interact ability?
Would you mind clarifying?
You can use creative target filters and buff applications to ensure that, while a neutral building remains neutral, it will still only sell items to one team.
All of the differences are listed in the section "the problem". I needed it to work with more than one player at a time - simulataneously. I needed warp gates to work. I got a few extra benefits as well, like individual queues/cooldowns. Believe me, I wouldn't have gone to all this trouble if the interact ability did what I needed it to.
Even if I could find a data solution, I've come to really like the individual queues that are actual visible. I don't think I'd use a data solution that didn't offer this functionability as well.
Well the differences in "the problem" section can all be worked around using data.
Individual cooldowns can't be though as far as I know.
A great deal of what I did is done in data. Most of the code I posted above are comments. There's really only about 20 lines of code. Even if it could be done in data, I haven't found a way and that solution isn't posted anywhere. I came up with a solution and I wanted to share it with people who might want to use it. It feels like you're trolling. You're just saying that it can be done, but not offering any actual solutions. By contrast, I offer an actual solution.
I've been a long way down that road, tried a lot of things, and asked a lot of people. I'm not nearly as convinced as you are that it actually can be done in data. However you think it could be done in data, I've probably already tried.
Saying "it can be done in data" is a lot different than spending hours building a tutorial to try and help people. There isn't a good solution out there, so I shared mine. If you have alternatives, help people out and post them. Otherwise, you have no right to try and take this away from me or any one else.
Also, the difference is minimal if at all. My triggers were built with performance in mind. They do little, if anything, more than what a data solution would do. The game still needs to scan objects and check conditions. It just does that in triggers instead of data in a few cases. My triggers were designed to only fire when they need to, and quickly dismiss if the conditions aren't meant. How much performance can that really take? There are no periodic triggers.
The other problem with the data editor is that a lot of times it requires a great deal of redundant work. Even setting up the requirements for this solution is quite redundant, for example. It's likely that any solution you offer would require several objects for each specific type of unit. Since I wanted to use my solution on every type of unit producing structure in the game, I want to avoid large amounts of redundant work. I still kept the redundant work on the requirements because that's what worked best. Keep in mind though, redundant work means redundant changes later down the road, which introduces the possibility of error. From a programmer's perspective, this is very bad.
The one problem with this solution, which we tried to solve yesterday on IRC, is that the real per-player selectable buildings aren't properly be hidden behind the dummy building (which is the visual representation of the building and takes damage). However, now that I noticed you did the damage sharing using triggers, I think my way of showing only one building per player or player group will actually work with this. You'll actually use the same number of buildings and you won't need your Selection trigger at all (removing the selection lag, wooo).
The problem now is that you'd need to share its vision with its enemies when you want them to see it. :( However, I think you could work around this by setting its sight radius to 0 and only sharing its vision when an enemy unit is in its own vision range with the building... Uh, that part sounds a bit tricky. I'll post this solution anyway since some (especially co-op) maps might not care that the building can be seen by enemies all the time.
So, instead of using a "dummy building", just place one visible, damageable building at the same spot for each player who can buy stuff from it (owned by that player), and one for the enemies (or other players) who can't buy stuff from it (owned by an ally of the players who can buy stuff from it). Check the "Buried", "Cloaked", and "Undetectable" flags for the building in data editor (Buried removes the distort effect from Cloaked, Cloaked makes it invisible to others and Undetectable makes it not detectable by units with Detector). You might also be able to use your "Building - Ally Interact" behavior to enable those flags if you want.
Make none of the players share vision with each other, and if you want to share the vision of some other units, do that manually using the "Share vision of unit" action first at map initialization for all preplaced units and then every time a unit is trained/constructured. Make the extra building owned by some ally player, and share its vision with all enemy players (otherwise they wouldn't see it at all).
Lastly, make your damage sharing trigger share the damage with each of those buildings whenever any of them takes damage.
In conclusion, you have:
This is still very hacky and non-perfect so if anyone has any ideas, do share!
Some great suggestions, a1win, that ended up bearing some fruit. I ended up going away from the "undetectable" flag, and instead using detection to reveal units. It's a lot less "hacky" than trying to reveal units manually. The purpose of detection is to reveal units, it just needed a few tweaks.
The changes are posted in the original post. The changelog at the beginning itemizes these changes.
why dont you use actors that make the hidden units invisible?
I dont see the point of all this vision stuff. I also dont understand why you need a gateway that all the players from a team can build from and still have the building destructable.
Maybe in certain circumstances.
I guess good job for getting to a point in your own map where you got it to work.
From reading though your wall of text, I couldnt really tell what your soloutions were actually a soloution to.
I have made some of my own hero shops. What I do Is put a building for each player on top of eachother and set the actor for it so that the actor is only visible to the player that owns the building.... You could possibly then link the buildings together.
can we get a video or a screenshot of what this looks like in game? a video would be better. This sounds like exactly what I need but I just want to make sure before running head first and finding its doesn't quite do what I want
My situation is fairly unique, sure, but it's also fairly common in that I needed to go outside the bounds of what Ability - Interact could do. I figured detailing my plight might help others who are going down the same road. Not everyone is going to have the same requirements, but the need to extend the normal capabilities is a common requirement. The "stacking buildings on top of one another" seems to be a fairly common solution, but no one previous has really detailed how this could be done. Having overcome this goal with some pretty steep requirements, I figured I'd offer my solution.
I'd be interested in hearing how you overcame your problem with actors. I did a lot of toying with actors in building my solution, but didn't have a lot of luck. The detection solution I came up with just today. It sounds complicated, but it's really not. Detection has some pretty powerful filters, so I abused them a little.
It is a wall of text, isn't it? I'm afraid to add screenshots because that will make it even longer. I'll post a sample map soon, so you can see how the interaction works. Perhaps I'll remove all the code and let the code in the sample speak for itself (with all the comments).
I'd also like to know how to make a unit actor only show the unit to its owner (or some other player). It annoys me when people reply with "why don't you just do X" without explaining how to actually do X when they can clearly see that the other person doesn't know how to do X, since otherwise he'd have done so in the first place. So please, everyone, less trolling, more sharing your ideas with those who want to learn.
@jaminv: Go
Just add pictures to your post, they will be located at the bottom of your post, and if you attach a video you can attatch it at the end of your post.
There are properties on unit actors that set who they are visible too.
Do you mean Actor - Filters? It has flags for Ally, Enemy, Neutral, and Self, but they are all disabled by default, and enabling some of them doesn't make the actor invisible to the others. So it doesn't work. Is there some other property that does what you're saying? Have you actually tried that it works or are you just saying it because it looks like it can be done?
Are you being intentionally vague? Do you think you could be a little more specific?
Even if this is the case, unless you can set these properties in triggers I don't see it being much use past a few buildings, since you'd need a seperate actor for the players and the enemies for each building. If such a thing were all data, it wouldn't scale well to lots of buildings. But, since you can't seem to tell me how to do this, I can't say for sure...
Herein lies the problem with this scenario. Everyone seems to be saying "you can do it way", or "I did it this way", but there's a decided lack of concrete information. So at this point I'm going to have to call malarkey on any recommendations that aren't backed with specific information. If I can't test it to see if it does in fact work, then it doesn't even exist.
@jaminv: Go
Umm... Specific as go look at unit actors and look at the visibility setting of the actor in question? I dont see that as being all that complicated.
Specific as in which frickin field, buddy? They have names, you know. Because I don't see it. Search for "visibility" on an actor object and you won't see it either. The only other option is "Actor - Flags", which we tried, and it doesn't work.
Unless you can give me a specific field name, the option doesn't exist.
Specific (adj): specifying, explicit, or definite.
He probably was referring to the field Filter, which can filter actors for specific players. Unfortunately, this field seems to have no effect for unit actors.
Well Im sorry I dont have an exact field name for you. Ill have to take a look at my map when I get home. I havent looked at that one for awhile.
Pretty sure I had it hiding the model from players who didnt own the unit. Ill get back to you after I open up my map later tonight.
I'm sorry to be curt with you, it's just that I've chased a lot of wild geese and been given a lot of hollow suggestions. I want to make sure you know, I am open to suggestion, and I am still looking for a "more perfect" solution. However, I need something concrete to go on. Otherwise, what I have works. Frankly, it actually works pretty well.
--
I've attached a sample map. I think it gives a really good demonstration of how everything works. It's actually set up for two players if you can get anyone else in on it. Having two players demonstrates it the best.