• 🏆 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!

[Trigger] More efficient method to keeping variables?

Status
Not open for further replies.
Level 4
Joined
Jul 14, 2012
Messages
100
[Solved] More efficient method to keeping variables?

First I would like to point out I am not using Jass, but standard triggers.

Not sure if this is the right place to ask but I'm having some size-issues with the way I've been making some triggers for my map. It contains 100 regions, and i labeled the regions 1-100, and my game revolves around only 1 of a certain unit-type per region(villages).

I want to give each "village" its own statistics(Happiness, etc.), but is there an easier way to keep tab? Currently this is how I planned to make the triggers for Happiness...

scrnsht2-2.png



scrnsht1.png


And the list goes on for all 100 regions.

But is there a more efficient way to do this? Please help as this will make the map a lot bigger.
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Of course there are better ways. It can be done in one tigger only and pre-determined data.

What's the logic in the relations between the regions and the villagers?
What influence the regions have on villagers?
What influence the villagers have on regions?

Let me know more details about what you want so I can help you.
 
Level 4
Joined
Jul 14, 2012
Messages
100
Ok so basically this is how it works. Settlers are units that create these villages when they cast an ability called Establish Village. I used the above triggering to check region to see if it was unoccupied, and if not, replace the settler with a Chieftan Hut and then create a couple villagers.

Happiness is a key component to villages I would like to add so as to add more strategy and intensity into the game. I want each village(as there is only one allowed per region, aka piece of land that is already physically defined in-game will marble tile borders) to have its own Happiness.

So say you have 5 Villages, all of which nothing has happened. They are at 35 Happiness initially, so everything seems fine. However, if a village gets conquered by an enemy, that village will lose 5 Happiness, bringing it down to 30, and all your other villages lose 3, taking them to 32. If the opponent chose not to sieze the village, and rather to just raze it, your villages instead will lose 4 Happiness each. However, those numbers dont include the fact that villages gain 1 Happiness every 45 seconds.

I easily found a way to trigger it where all villages owned by a player share the same Happiness, but then that was pointless because then all people had to do was keep it just above 0, as hitting 0 meant that village revolted and you lost control of it. That made the concept stupid because then you ultimately lose the game without any chance.

Thats why i decided i want each city to have its own happiness. Other factors that affect happiness would be
1. One of your villages revolts(you lose 3xn Happiness, where N is the current number of revolting cities. So at the first revolt, all other villages lose 3 Happiness. If another one revolts, all other villages lose a cumulative 6 happiness, making a total of 9. If another revolts, they all lose 9 happiness, making a total of 18, and so on)
2. You are the last to reach the next age. For example, every one starts in the Ancient Age and it announces whenever someone reaches the next age, which in this case(after Ancient) is the Medieval. It says whenever someone is First or Last, so the Last person to reach the next age has a penalty of all his villages losing 5 Happiness.
3. You declare war on someone- every time to choose to declare war on someone, all your villages lose 2 Happiness.
4. You are at 80% of your food limit. And by this I dont mean the max food supply(which i made 300), i mean your current one, which may be 10 or 20 or whatever. This is unhappiness by crowding and you lose 1 Happiness every 60 seconds until you free more room for your people.
5. High Tax Rate- Once in the Medieval Age, a technology called Taxation becomes available after some prerequisite researching. It allows you to gain 1 gold per every village you have every 60 seconds. This is the "low" tax rate, which means your villages will still gain happiness over time, yet slower. The "medium" tax rate is 1 gold per village every 45 seconds, which basically stunts happiness growths. The "high" tax rate is 1 gold per village every 30 seconds, which slowly decreases happiness over time. Additionally, having "high" tax rate for periods longer than 5 minutes causes all villages to instantly lose 7 Happiness. You can only adjust the tax rate every 1 minute and 30 seconds(you technically click a button to adjust it, but it takes 1 minute and 30 seconds before effect is taken and casting time, since the button used to adjust tax rate will be an ability).
6. Influential Figure attack- Influential figures are invulnerable units that can be consumed in order to add flat Happiness to one of your villages or decrease Happiness of a civilization owned by another player. -4 Happiness to that village. Influential figures can be easily blocked with a wall+gate as they have no entry in your civilization.

Additionally, here are ways to Gain Happiness:
1. Be the first to reach the next age(+7 Happiness to all villages)
2. Ally with someone(+1 Happiness to all villages)
3. Having a Low Tax Rate(see above)
4. Research certain technologies grants a flat amount of happiness to be granted instantly to all villages(ex: researching Literature in the Renaissance Age grants a flat +10 Happiness to all villages)
5. Settle an Influential Figure into a village +10 Happiness in that particular village
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Damn, it's way too complicated. There are too many units and regions involved, besides "Villages" and revolts, and stuff.

How are villages conquered?

A first step is pre-setting all the regions into a hashtable, and save True/False into the region ID. When you build something there, you save "True". If 1 of RegionID equal to false then... else..."

Then, I Would suggest pre-creating the 100 floating texts connecting them with their corresponding regions (saving the floating text ID into the regions ID)

Make a "TownHall" or "TownCenter" what represents the town itself, and save the FloatingTextID within that TownHall. Add that Townhall to a TownHallGroup, where you add all the TownHalls. From there on, whenever you want to modify the happiness of a village, you access to the TownHall ID to modify it. The idea is to avoid creating a floating text every 5 secs.

When alliance occurrs, you pick every unit in TownHallGroup and if the picked unit belongs to the players that are stablishing the alliance, you set their happiness to +1. Do the same thing with all the others stuff.

I would suggest you to plan everything, and check how everything is connected, then understand the way everything is connected (the logic between them all). Since the system requires several different systems working together is hard for me to create it, since, modifying something in one place, may change everything else, that's why I suggest you to plan it. Anyway, we can discuss here ways to achieve what you want and help you to create it yourself.
 
Level 4
Joined
Jul 14, 2012
Messages
100
Villages are conquered when the townhall-unit type structure within the region gets destroyed. A dialog box is then displayed to the conqueror whether or not he would like to
1. Sieze the village
2. Raze the village

And it goes on from there.

Also, ive already triggered the regions to become "occupied" once a village is settled there. Settling in villages works already- all settlers come with an ability called Establish Village which activates the trigger and I want to use the same concept to make Influential Figures except reversing the Conditions to where a village IS needed in order for the ability to take effect.

But the way I triggered the Establish Village was how I was about to trigger the Happiness. I made 100 If/Then/Elses on an INCREDIBLY long action. I then broke it up into 20 or so actions for simplicity, and put 10 of those into a separate trigger just so that one trigger isnt so bundled.

But that process took FOREVER and I had to go through it sooo many times to make sure each land worked as typoes ruined it. I want to avoid that trouble and find another way.

If i saved the floating text as an ID to its corresponding region, would the the text within it be active? The problem I had with the text is that to display Happiness, i put Convert Integer to String, where the integer is an integer called Happiness(its an integer array of 100 for all 100 lands).

But when that Happiness[x] changed, the floating text didnt. So even though happiness[x] was, say, 20. The floating text would still say 35. It doesn't keep updated and thats why I made that 2nd trigger. Unless the idea you proposed with the ID's made them constantly active?

Also I've never used hashtables or IDs, so I'm not even sure how to use those..?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
What I want is to avoid those 100 If/Then/Else when you can do it with just one.

Everything in Warcraft has an ID. Just as any point of the map has an specific X/Y, every unit, tree, bird, unit, group, unit-type, item, item-type, has it's own specific ID, which is unrepeateable within the game. It's the CodeBar of the widget. That can be used to manipulate specific objects by just knowing its ID.

The Hashtable is a way to index stuff, it's like an Array but with two dimensions (Arrays Goes from 0 to 8190, Hashtables goes from 0,0 to infinite,infinite.)

I'll work a bit on this and update my post later.

<< EDIT >>

You'll have to use JASS for this...
 
Last edited:
Level 4
Joined
Jul 14, 2012
Messages
100
If there is truly no other way to shortcut this than to use Jass, I'll probably just make the 100 if/then/elses, seeing as I have no experience whatsoever with Jass.

I appreciate your effort to help me anyway, though.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I can do it for you, at least a short example and let you do the rest, but I don't have time right now, maybe later (in about 5 hours). It's easy, and JASS is pretty understandable. I'll comment everything to make it easier for you.

It's not about using GUI or JASS, it's about making it the most efficient way to make it work faster, better, and... in the end, the easiest way and less time consuming way.
 
Level 16
Joined
Oct 12, 2008
Messages
1,570
Why not create a region array, for instance called "Village_Regions", and set it to the regions, for instance, "Set Village_Regions[1] = 1 <gen> " or whatever it should be, and then loop through the regions. That's how I would probably do it (if I would use GUI).
 
Level 4
Joined
Jul 14, 2012
Messages
100
Could you possibly provide an example, Yixx? Not quite sure how that might work.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Create an Integer Variable: i
Create a Region Variable: Reg

For each integer A from 1 to 100 do:
If Region[Integer A] contains Triggering Unit then
Set i = [Integer A]
set Region = Region

That way the value of i will be equal to the value of Integer A when Integer A is equal to the region that contains the unit that's settling the village. So.. i will be equal to the index of the region you're at. That's "Brute-force" search. If the villager is at region 99, you'll make 98 unusefull and resource consuming searches.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Another way (better, but a bit harder)
1. Create a Hashtable (Hash)
2. Locally, create all the 100 Regions (R1, R2, etc.)
3. Add the 100 Rects (1, 2, 3) to the Regions (R1, R2, R3)
4. Locally, get the Handle ID of the Regions (R1, R2, R3)
5. Save False as 0 of ID in Hash (As "Region isn't occupied")
6. Save 0 as 1 of RegID in Hash (As Happines)
7. Globally, create the TextTag (Floating Text) at the CenterX and CenterY of the Rects (1, 2, 3)
8. Locally, get the Handle ID of the TextTags
9. Save the ID of the TextTags as 2 of RegID in Hash
10. When a TownHall is created, save the ID of the Region where it was created as 0 of of the TownHall ID, and save True as 0 of RegID in Hash. Also add the TownHall to a TownHallGroup (Unit Group)

From there on...

· If you want to modify the Happiness of towns of players, you Pick Every TownHall from TownHallGroup, you load the Regions they own from 0 of the Picked Townhall ID, and save +X as 1 of RegionID in Hash. (I mean, you increase the value in that field by X)

· When you do the Influential Figure thing, you have to detect the region where it was settled (with a brute search, I guess), or it's distance to the nearest TownHall.

This way, you just need to know the TownHall or Region to manipulate everything else. Whenever a hapiness change, you can update all the TextTags to display: "Happiness: (Load 1 of RegID)"


ANOTHER WAY (A bit easier) is to determine the regions, not by regions, but by Geographical separations, I mean... make the "Village Regions" buildable terrain, and make everything else "Unbuildable" so, you just have to detect and work with the TownHalls and else, and forget about the regions.
 
Level 4
Joined
Jul 14, 2012
Messages
100
The distance between the town halls would not be an accurate way of determining which land the influential figure is in because

1.) The lands are not the same size
2.) When a village is settled, it is not a predetermined part of the land. It is at the location of the settler.

With that in mind, an Influential Figure could be in one Land, large and where the town hall is far yet still in that land, while next to a land that is smaller and has a nearby Town Hall. If it were to be set up to where it would depend on which one he was closer to, he would affect the wrong village.

Thus the buildable idea you had thought of wouldnt work either, especially since there is no unbuildable terrain besides the cliffs and water. The borders are just using distinctive buildable terrain.

Also, it doesnt look neat when a village's town-hall-type unit is on one side of a land, and floating text is in the center, or that floating text is there when a village is not(unless I misinterpreted that part)

Additionally, units made after the floating text will float over the text, so I wanted to make the text spawn at a certain offset from where-ever the village is spawned. So im not sure if that would work with the floating text?

Regardless, of all the steps you gave, I only understood half of them. I've never done hashtables before, so all this reference to ID's and tags just confuses me. I would understand it better with some sort of picture or example, if one exists already?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
(You did missinterpreted that part, at first i was talking about region center, but if you build a townhall, you can instead work with the TownHall)

Additionally, units made after the floating text will float over the text, so I wanted to make the text spawn at a certain offset from where-ever the village is spawned. So im not sure if that would work with the floating text? <- I Didn't understand.

1. Create a Trigger. Call it VillageSettlement
2. Select it
3. Go to "Edit"
4. "Convert to Custom Text"
5. Delete everything inside and paste
JASS:
function VillageSettlement_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'hfoo' 
/* This 'hfoo' has to be replaced the Unit-Type Raw ID of the TownHall, 
you can see it by pressing  "CTRL+D" in the Object Editor. You'll se 
everything has a different ID.
   
What this does is check if the Unit-Type of the unit that enters any of the 
listed regions is a Town Hall. 

All this green lines can be deleted */
endfunction

/* Anything placed in the VillageSettlement_Actions will happen only if the unit 
that enters any of the regions is a TownHall */

function VillageSettlement_Actions takes nothing returns nothing
/* Here's where we'll make everything else, based on the TownHall */
    
    local unit u = GetTriggerUnit() // The Triggering Unit (The TownHall)
    local integer i = GetHandleId(u) // The Handle ID of the TownHall
    local hashtable h = udg_Hash // h is easier than "udg_Hash".
    local integer RID = GetHandleId(GetTriggeringRegion())
    local integer pn = GetPlayerId(GetOwningPlayer(u)) + 1  // The Player Number of the Owner of the TownHall
    local integer TotalHappiness = udg_Happiness+udg_GlobalModifiers[pn]
    local texttag TT = CreateTextTag() // The Floating Text
    local integer TTID = GetHandleId(TT) // The Floating Text ID
    
    
    
    // udg_Hapiness is an Integer Variable for Default Hapiness
    // udg_GlobalModifiers is an Integer Variable Array for player actions that affects
    // the happiness of all towns (upgrades, alliances, revolts, etc.) of that player
    
    call GroupAddUnit(udg_TownHalls, u) // This adds the TownHall to the TownHalls group.
    
    call SaveBoolean(h, RID, 0, true) // Means the Region was occupied
    
    call SaveInteger(h, i, 0, TotalHappiness) // We save the Hapiness into the TownHall ID
    call SaveInteger(h, i, 1, 0) // We'll use this to modify just this town hapiness
    call SaveInteger(h, i, 2, TTID) // The TextTag ID to modify it later
    
    //These 3 following actions are for the Floating Text
    call SetTextTagText(TT, "Happiness: " + I2S(TotalHappiness), 10 * 0.023 / 10) // the first 10 is the Size
    call SetTextTagPos(TT, GetUnitX(u), GetUnitY(u), 10.00) // This 10.00 is the Height
    call SetTextTagColor(TT, 255, 255, 255, 255) // These are red, green, blue, and alpha
    
    // Cleaning Leaks
    set u = null 
    set h = null
    set TT = null
endfunction

//===========================================================================
function InitTrig_VillageSettlement takes nothing returns nothing

    set udg_Hash = InitHashtable() // This requires a Hashtable variable creation called "Hash".

    // Create a Region Array and call it "Regions"
    
    local region R1 = CreateRegion()
    call RegionAddRect(R1, gg_rct_1)
    call TriggerRegisterEnterRegion(gg_trg_VillageSettlement, R1, null)
    call SaveBoolean(udg_Hash, GetHandleId(R1), 0, false)
    
    local region R2 = CreateRegion()
    call RegionAddRect(R1, gg_rct_2)
    call TriggerRegisterEnterRegion(gg_trg_VillageSettlement, R2, null)
    call SaveBoolean(udg_Hash, GetHandleId(R2), 0, false)
    
    local region R3 = CreateRegion()
    call RegionAddRect(R1, gg_rct_3)
    call TriggerRegisterEnterRegion(gg_trg_VillageSettlement, R3, null)
    call SaveBoolean(udg_Hash, GetHandleId(R3), 0, false)
    
    local region R4 = CreateRegion()
    call RegionAddRect(R1, gg_rct_4)
    call TriggerRegisterEnterRegion(gg_trg_VillageSettlement, R4, null)
    call SaveBoolean(udg_Hash, GetHandleId(R4), 0, false)

/* R1, R2, R3, R4 are the regions
gg_rct_1, gg_rct_2, gg_rct_3, gg_rct_4 are the rects (what you create in the editor). 
The system adds "gg_rct_*" to the name of the region. Continue with all the 100 regions 
the same way those 4 were made. */

call TriggerAddCondition( gg_trg_VillageSettlement, function VillageSettlement_Conditions )
call TriggerAddAction( gg_trg_VillageSettlement, function VillageSettlement_Actions )
endfunction

<< EDIT >>

Done, that seems to cover pretty much everything. That trigger alone will detect whenever you create a TownHall on any of the regions, and will save the default hapiness (stored in a variable) plus (or minus) the Player Global Modifiers (Alliances, revolts, etc.) in the TownHall ID, will also create the TexTag that displays ("Hapiness: " + Hapiness) and stores the TexTag ID in the TownHall.

The Following one Updates the Hapiness every 5 seconds.

  • Hapiness Update
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in TownHalls and do (Actions)
        • Loop - Actions
          • Custom script: local integer i = GetHandleId(GetEnumUnit())
          • Custom script: local texttag TT = LoadTextTagHandle(udg_Hash, i, 2)
          • Custom script: call SetTextTagText(TT, "Happiness: " + I2S(udg_Happiness+udg_GlobalModifiers[GetPlayerId(GetOwningPlayer(GetEnumUnit())) + 1]+LoadInteger(udg_Hash, i, 1)), 10.00)
If you want to modify specific town hapiness, just detect the village TownHall, get it's ID, load the value stored in 1 of the ID in Hash, and add or substract what you want from the value that was already there (which is 0 by default)

In the example I save the Handle Id of the unit in the "i" integer., then I store the specific town hapiness as LH, then I add 3 to LH and store it again. Event and Conditions are just examples. You'll have to modify it to suit your way.
  • Example
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Footman
    • Actions
      • Custom script: local integer i = GetHandleId(GetTriggerUnit())
      • Custom script: local integer LH = LoadInteger(udg_Hash, i, 1)
      • Custom script: call SaveInteger(udg_Hash, i, 1, LH+3)
You just need
· GlobalModifiers (Integer Array)
· Happiness (Integer)
· Hash (Hashtable)
· Village (Integer)
· TownHalls (Unit Group)

<< EDIT >>

Let me know if you have any doubt or have any problem. This is not "perfectly done" because you have to adjust it to the systems you already have. I tried to be as clear as possible to make it easier for you to understand. If you had this complicated idea about working with hapiness, i'm sure you can see how I did this and understand how it works. You need JNPG to make this work.

<< EDIT >>

Mmm.. I was thinking that, instead of having a Global Modifier array for Hapiness, you could just locally modify each TownHall hapiness with a "Pick Every Unit".
 
Last edited:
Level 4
Joined
Jul 14, 2012
Messages
100
To my understanding, anything created After a floating text was created, appears over it. Think of a pancake. Whichever one made first goes under. I don't want units to be walking over the text, thats why I want it to be a certain offset from whereever the location of the town hall is. For example, if the townhall is at position (x,y), i want the text to refer to that and be at location (x+20, y+60) sort of thing. (those were just random numbers)
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Don't worry. The height can be easily modified later. Default height is usually over the units. I'm editing the last post to achieve everything. I used 10 as a random number.

<< EDIT >>

Did the final edit of my last post to show you the triggers and stuff.
 
Last edited:
Level 4
Joined
Jul 14, 2012
Messages
100
Looks thorough. I really appreciate you doing this, I'll give some time and read over it a bit then post later if it works. Thanks :D
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Hehehe... I made it a lot easier

As long as your hashtable is called "Hash" and your trigger name for village settlement is called "VillageSettlement" this should work

JASS:
//Copy this in your map header. A small map icon with your map name at the top of the trigger list
function AddRegion takes rect r, integer index returns event
    local region rectRegion = CreateRegion()
    call RegionAddRect(rectRegion, r)
    call SaveBoolean(udg_Hash, GetHandleId(rectRegion), 0, false)
    set udg_Region[index] = r
    return TriggerRegisterEnterRegion(gg_trg_VillageSettlement, rectRegion, null)
endfunction

Then, in VillageSettlement trigger, instead of this
JASS:
    local region R4 = CreateRegion()
    call RegionAddRect(R1, gg_rct_4)
    call TriggerRegisterEnterRegion(gg_trg_VillageSettlement, R4, null)
    call SaveBoolean(udg_Hash, GetHandleId(R4), 0, false)
you just need to do
JASS:
call AddRegion(gg_rct_1, 1)
call AddRegion(gg_rct_2, 2)
call AddRegion(gg_rct_3, 3)
call AddRegion(gg_rct_4, 4)

Improved the code a bit, no need for many things I was doing. Now you just one one Integer Array variable called "Happiness" and set it's default value to what you want to be the default Happiness in the game (35). This way, you just modify hapiness for each player using it's player-number as the Happiness index. I'm still working on some other stuff you asked for.
JASS:
function VillageSettlement_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) == 'hfoo' // This 'hfoo' has to be the ID of the TownHall 'xxxx'
endfunction

function VillageSettlement_Actions takes nothing returns nothing
    
    local unit u = GetTriggerUnit() // The Triggering Unit (The TownHall)
    local integer i = GetHandleId(u) // The Handle ID of the TownHall
    local integer RID = GetHandleId(GetTriggeringRegion())
    local texttag TT = CreateTextTag() // The Floating Text
    local integer TTID = GetHandleId(TT) // The Floating Text ID
    
    call GroupAddUnit(udg_TownHalls, u) // This adds the TownHall to the TownHalls group.
    
    call SaveBoolean(udg_Hash, RID, 0, true) // Marks the Region as occupied
    
    call SaveInteger(udg_Hash, i, 0, udg_Happiness[GetPlayerId(GetOwningPlayer(u)) + 1])
    call SaveInteger(udg_Hash, i, 1, 0) // We'll use this to modify just this town hapiness
    call SaveInteger(udg_Hash, i, 2, TTID) // The TextTag ID to modify it later
    
    //These 3 following actions are for the Floating Text
    call SetTextTagText(TT, "Happiness: " + I2S(LoadInteger(udg_Hash, i, 0)-LoadInteger(udg_Hash, i, 1)), 10 * 0.023 / 10)
    call SetTextTagPos(TT, GetUnitX(u), GetUnitY(u), 10.00) // This 10.00 is the Height
    call SetTextTagColor(TT, 255, 255, 255, 255) // These are red, green, blue, and alpha
    
    // Cleaning Leaks
    set u = null 
    set TT = null
endfunction

//===========================================================================

function InitTrig_VillageSettlement takes nothing returns nothing

set udg_Hash = InitHashtable() // This requires a Hashtable variable creation called "Hash".

// Function AddRegion(gg_rct_*rectname*, Index)
call AddRegion(gg_rct_1, 1)
call AddRegion(gg_rct_2, 2)
call AddRegion(gg_rct_3, 3)
call AddRegion(gg_rct_4, 4)
//Continue untill all your VillageRegions are added

call TriggerAddCondition( gg_trg_VillageSettlement, function VillageSettlement_Conditions )
call TriggerAddAction( gg_trg_VillageSettlement, function VillageSettlement_Actions )
endfunction

<< EDIT >>

I made this filter to know in which region the unit is standing at, and to know if the region is already occupied or not. You have to create a trigger called "SettlementFilter", convert it to custom text, delete everything inside, and paste the following.

JASS:
function SettlementFilter_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'AUan' // This should be the ID of your "Settlement" Ability
endfunction

function SettlementFilter_Actions takes nothing returns nothing
// The following is to detect in which region the unit is trying to settle.
    local unit u = GetTriggerUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    
    local integer id
    local integer index
    
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 100
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        if (GetRectMinX(udg_Region[bj_forLoopAIndex]) <= x) and (x <= GetRectMaxX(udg_Region[bj_forLoopAIndex])) and (GetRectMinY(udg_Region[bj_forLoopAIndex]) <= y) and (y <= GetRectMaxY(udg_Region[bj_forLoopAIndex])) then
            set index = bj_forLoopAIndex
            set bj_forLoopAIndex = 100
        endif
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    set id = GetHandleId(udg_Region[index])
    if LoadBoolean(udg_Hash, id, 0) == true then
        // This happens if the region is occupied
        call DisplayTimedTextToPlayer(GetTriggerPlayer(), 0, 0, 10, "|cffff0000Region already occupied|r")
    else
        // Here's where you create the TownHall for the player. You can do the actions in GUI, convert them to Custom Text, and paste them here, replacing this comment.
        // The rest happens automatically when the TownHall is created.
    endif
    
    set u = null
endfunction

//===========================================================================
function InitTrig_SettlementFilter takes nothing returns nothing
    set gg_trg_SettlementFilter = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_SettlementFilter, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_SettlementFilter, Condition( function SettlementFilter_Conditions ) )
    call TriggerAddAction( gg_trg_SettlementFilter, function SettlementFilter_Actions )
endfunction

This is the GUI Hapiness update every 5 seconds

  • Hapiness Update
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in TownHalls and do (Actions)
        • Loop - Actions
          • Custom script: local integer i = GetHandleId(GetEnumUnit())
          • Custom script: local texttag TT = LoadTextTagHandle(udg_Hash, i, 2)
          • Custom script: call SetTextTagText(TT, "Happiness: " + I2S(LoadInteger(udg_Hash, i, 0)-LoadInteger(udg_Hash, i, 1)), 10 * 0.023 / 10)
SO FAR

- The system will index the 100 regions in a Region array and save "false" as they all start unoccupied
- When you use "Settlement" the system checks in which region your unit is at, and checks if it's occupied or not. If it's occupied, it displays a message, if it isn't, you have to add the actions to create the TownHall and special effects and anything you want.
- Automatically, when the TownHall is created, the system will create the Floating Text displaying hapiness at position of TownHall, will also set the region as occupied,
- Automatically, hapiness message will be updated every 5 seconds

I would suggest you to make tests with 5 or 10 regions before adding all the 100 to the list.
 
Last edited:
Level 4
Joined
Jul 14, 2012
Messages
100
Wait so do you want me to just go through this post or the other one? Is the other one obsolete now compared to these?
 
Level 4
Joined
Jul 14, 2012
Messages
100
Okay so after thinking about what you said and my failed attempts at comprehending Jass, I've tried to pull it off with triggers...

This first trigger defines all the regions prior to the game starting:

  • Preloading game
    • Events
    • Conditions
    • Actions
      • Set region[1] = 1 <gen>
      • Set region[2] = 2 <gen>
      • Set region[3] = 3 <gen>
      • Set region[4] = 4 <gen>
      • Set region[5] = 5 <gen>
      • Set region[6] = 6 <gen>
      • Set region[7] = 7 <gen>
      • Set region[8] = 8 <gen>
      • Set region[9] = 9 <gen>
      • Set region[11] = 11 <gen>
      • Set region[12] = 12 <gen>
      • Set region[13] = 13 <gen>
      • Set region[14] = 14 <gen>
      • Set region[15] = 15 <gen>
      • Set region[16] = 16 <gen>
      • Set region[17] = 17 <gen>
      • Set region[18] = 18 <gen>
      • Set region[19] = 19 <gen>
      • Set region[20] = 20 <gen>
      • Set region[21] = 21 <gen>
      • Set region[22] = 22 <gen>
      • Set region[23] = 23 <gen>
      • Set region[24] = 24 <gen>
      • Set region[25] = 25 <gen>
      • Set region[26] = 26 <gen>
      • Set region[27] = 27 <gen>
      • Set region[28] = 28 <gen>
      • Set region[29] = 29 <gen>
      • Set region[30] = 30 <gen>
      • Set region[31] = 31 <gen>
      • Set region[32] = 32 <gen>
      • Set region[33] = 33 <gen>
      • Set region[34] = 34 <gen>
      • Set region[35] = 35 <gen>
      • Set region[36] = 36 <gen>
      • Set region[37] = 37 <gen>
      • Set region[38] = 38 <gen>
      • Set region[39] = 39 <gen>
      • Set region[40] = 40 <gen>
      • Set region[41] = 41 <gen>
      • Set region[42] = 42 <gen>
      • Set region[43] = 43 <gen>
      • Set region[44] = 44 <gen>
      • Set region[45] = 45 <gen>
      • Set region[46] = 46 <gen>
      • Set region[47] = 47 <gen>
      • Set region[48] = 48 <gen>
      • Set region[49] = 49 <gen>
      • Set region[50] = 50 <gen>
      • Set region[51] = 51 <gen>
      • Set region[52] = 52 <gen>
      • Set region[53] = 53 <gen>
      • Set region[54] = 54 <gen>
      • Set region[55] = 55 <gen>
      • Set region[56] = 56 <gen>
      • Set region[57] = 57 <gen>
      • Set region[59] = 59 <gen>
      • Set region[60] = 60 <gen>
      • Set region[61] = 61 <gen>
      • Set region[62] = 62 <gen>
      • Set region[63] = 63 <gen>
      • Set region[64] = 64 <gen>
      • Set region[65] = 65 <gen>
      • Set region[66] = 66 <gen>
      • Set region[67] = 67 <gen>
      • Set region[68] = 68 <gen>
      • Set region[69] = 69 <gen>
      • Set region[70] = 70 <gen>
      • Set region[71] = 71 <gen>
      • Set region[72] = 72 <gen>
      • Set region[73] = 73 <gen>
      • Set region[74] = 74 <gen>
      • Set region[75] = 75 <gen>
      • Set region[76] = 76 <gen>
      • Set region[77] = 77 <gen>
      • Set region[78] = 78 <gen>
      • Set region[79] = 79 <gen>
      • Set region[80] = 80 <gen>
      • Set region[81] = 81 <gen>
      • Set region[82] = 82 <gen>
      • Set region[83] = 83 <gen>
      • Set region[84] = 84 <gen>
      • Set region[85] = 85 <gen>
      • Set region[86] = 86 <gen>
      • Set region[87] = 87 <gen>
      • Set region[88] = 88 <gen>
      • Set region[89] = 89 <gen>
      • Set region[90] = 90 <gen>
      • Set region[91] = 91 <gen>
      • Set region[92] = 92 <gen>
      • Set region[93] = 93 <gen>
      • Set region[94] = 94 <gen>
      • Set region[95] = 95 <gen>
      • Set region[96] = 96 <gen>
      • Set region[97] = 97 <gen>
      • Set region[98] = 98 <gen>
      • Set region[99] = 99 <gen>
      • Set region[100] = 100 <gen>
      • Set region[101] = 101 <gen>
      • Set region[102] = 102 <gen>
      • Trigger - Run Start the Game <gen> (ignoring conditions)

This 2nd trigger settles a village when the player uses his settler's ability Establish New Village:


  • Village is Settled
    • Events
      • Unit - A unit Begins casting an ability
    • Conditions
      • (Ability being cast) Equal to Establish New Village
    • Actions
      • For each (Integer A) from 1 to 102, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (region[(Integer A)] contains (Triggering unit)) Equal to True
              • IsOccupied[(Integer A)] Equal to False
            • Then - Actions
              • Set IsOccupied[(Integer A)] = True
              • Set TempLoc = (Position of (Triggering unit))
              • Unit - Replace (Triggering unit) with a Chieftain's Hut using The new unit's max life and mana
              • Set village[(Integer A)] = (Last replaced unit)
              • Unit - Create 2 Ancient Villager for (Owner of (Triggering unit)) at TempLoc facing Default building facing degrees
              • Game - Display to (All players) the text: ((Name of (Owner of (Triggering unit))) + Has Settled A New Village!)
              • Special Effect - Create a special effect at TempLoc using Abilities\Spells\Items\ResourceItems\ResourceEffectTarget.mdl
              • Special Effect - Destroy (Last created special effect)
              • Floating Text - Create floating text that reads Village Happiness above village[(Integer A)] with Z offset 60.00, using font size 12.00, color (50.00%, 50.00%, 100.00%), and 0.00% transparency
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Change the lifespan of (Last created floating text) to 5.10 seconds
              • Floating Text - Create floating text that reads (String(villagehappiness[(Integer A)])) above village[(Integer A)] with Z offset 20.00, using font size 13.00, color (50.00%, 100.00%, 0.00%), and 0.00% transparency
              • Floating Text - Change (Last created floating text): Disable permanence
              • Floating Text - Change the lifespan of (Last created floating text) to 5.10 seconds
              • Skip remaining actions
            • Else - Actions
              • Do nothing
I also implemented my Happiness idea into that trigger.

EDIT: I had a problem with it, but I found that in a separate trigger, i had RemoveUnit trigger that would remove the unit xD ok it works now.

But anyway, was this what you meant Sparti? :O It works like a charm and so efficient and clean compared to my old method....
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
Well, you loop through 102 regions, when you could just detect the region you need. There you have 101 more comparisons than my trigger.

That's exactly what i DID NOT mean. That's exactly what i wanted to prevent: unnecessary loop through 102 regions, when you could just detect the one you need to.
 
Level 4
Joined
Jul 14, 2012
Messages
100
At least when it finds the region it needs, it stops searching :eek:

But do you suppose the above trigger would be efficient enough to not cause lags after enough runs? Does it leak?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Actually, no, it always searches through all the 102. You have to replace "Skip remaining actions" with "Custom script: set bj_forALoopIndex = 103" to stop the loop when it finds the correct one.

No, it doesn't leak, but it's just not efficient :p And woul dtake more memory space, really old and lame computers would be affected by the memory this trigger uses everytime it runs, it could probably do a small lag spike.
 
Level 4
Joined
Jul 14, 2012
Messages
100
Actually, no, it always searches through all the 102. You have to replace "Skip remaining actions" with "Custom script: set bj_forALoopIndex = 103" to stop the loop when it finds the correct one.

No, it doesn't leak, but it's just not efficient :p And woul dtake more memory space, really old and lame computers would be affected by the memory this trigger uses everytime it runs, it could probably do a small lag spike.

Ah, I see. But then again, lame and old computers may lag anyway from other simple warcraft things, so I'm going to assume my trigger pretty harmless.

Oh but for some reason when i put the custom script set bj_forALoopIndex = 103, it didn't recognize it. Was I supposed to apply the name of something into that generic command?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
then it's bj_forLoopAIndex instead of bj_forALoopIndex, my bad.

When you create "For Loop A" Warcraft 3 uses a "Loop A Minimum" and "Loop A Maximum" and "Loop A Index", it starts at minimum, and index increases, util it's higher than the maximum, that's why setting it to 103, to make it higher than 102 and make it stop.
 
Status
Not open for further replies.
Top