Skip to content

Posts from Scripts

4.8 (8 ratings)
User Avatar
Auto-translated
Hello, I have a couple of questions about your script: there cannot be a creature named "Priest" on the battlefield, just like there cannot be "Osillian" (if this is a variable that stores the correct name, then it's fine, but if you forgot the quotes, read on). All creatures have a composite script name in the form "coordinates+ID+number," and this name is stored in the first argument of the hook. In your case, this is the "unit" variable. But "Priest" and "Osillian" are not on the battlefield. Write a hook for the turn of the defending hero, and inside it, add a check: ```lua for n, creature in GetDefenderCreatures() do local id = GetCreatureType(creature) if id == CREATURE_ARCHER then local targets = GetAttackerCreatures() chosen_target = targets[random(length(targets)+1] -- actions with the archer creature and the chosen_target end end ``` You need to rewrite the "random" function because the standard one doesn't work. You can take the randomizer from Echoes of the Void by RedHeavenHero, if he doesn't mind, or write it yourself.
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
In reply to }{0TT@6bI4
User Avatar
Auto-translated

Thank you very much for your response. Yes, Osillian is a variable ("Osillian = GetDefenderHero()"), and 'Priest' is the name of the stack created by the AddCreature script. The random function is present. The only remaining issue is the hero's refusal to cast Heavenly Shield on a creature. The screenshot below shows the error that the console displays when attempting to cast it on a creature.

Another problem arose with the script you suggested. The error related to this is also present in the screenshot. Here is my random function:

Titlelocal default_state = {
    {1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0},
    {0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0},
    {1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0},
    {1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1},
}
function GetPRNGSeed(state)
    local col, row = 1, 4
    local seed = {0, 0, 0, 0, 0, 0}
    for i=1,6 do
        local p2 = 1
        for j=1,23 do
            seed= seed+ p2 * (%default_state[row][col] ~= state[row][col] or 0)
            p2 = p2 * 2
            row = row - 1
            if row < 1 then row, col = 4, col + 1 end
            if col > 32 then break end
        end
        if col > 32 then break end
    end
    return seed
end

function SetPRNGSeed(state, seeds)
    state = state or {}
    seeds = seeds or {}
    for i=1,4 do
        if not statethen
            state= {}
        end
        for j=1,32 do
            state[j] = %default_state[j]
        end
    end
    local col, row = 1, 4
    local si
    for i=1,6 do
        si = seedsor si
        if not si then break end
        local si = si
        for j=1,23 do
            local bit = mod(si, 2)
            si = (si - bit) / 2
            state[row][col] = state[row][col] ~= bit or 0
            row = row - 1
            if row < 1 then row, col = 4, col + 1 end
            if col > 32 then break end
        end
        if col > 32 then break end
    end
    return state
end

function NewPRNG(seeds)
    local state = SetPRNGSeed({}, seeds)
    local random = function(n, m)
        local state = %state
        local s
        local t = state[4]
        for i=1,21 do  -- t = t xor (t << 11)
            t= t~= t[i+11] or 0
        end
        for i=9,32 do  -- t = t xor (t >> 8)
            t= t~= t[i-8] or 0
        end
        state[4] = state[3]
        state[3] = state[2]
        s = state[1]
        state[2] = s
        for i=1,32 do  -- t = t xor s
            t= t~= sor 0
        end
        for i=20,32 do  -- t = t xor (s >> 19)
            t= t~= s[i-19] or 0
        end
        state[1] = t
        local r = 0
        local p = 1
        for i=24,1,-1 do
            r = r + p * t
            p = p * 2
        end
        r = r / 16777216
        if n then
            if not m then
                n, m = 1, n
            end
            return n + floor(r * (m - n + 1))
        else
            return r
        end
    end
    return random, state
end

function InitRandom()
    local seed_t = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
    local seed = {}
    local shift = 0
    for side = 0, 1 do
        for j, unit in GetCreatures(side) do
            local type = GetCreatureType(unit)
            local num = GetCreatureNumber(unit)
            local x, y = pos(unit)
            local n = mod(type, 180) + 180 * (x + 14 * (y + 14 * mod(num, 200)))
            shift = shift + 7
            for i=1,24 do
                local bit = mod(n, 2)
                n = (n - bit) / 2
                local index = mod(shift + i, 24) + 1
                seed_t[index] = seed_t[index] ~= bit or 0
            end
        end
        local x = 0
        local p = 1
        for i=1,24 do
            x = x + p * seed_t
            p = p * 2
        end
        for i=1,12 do
            seed_t, seed_t[25 - i] = seed_t[25 - i], seed_t
        end
        seed[side+1] = x
        seed[side+3] = x
        seed[side+5] = x
    end
    print('PRNG seed = ' .. seed[1] .. ':' .. seed[2])
    random = NewPRNG(seed)
end

And here is the script in which I use it:

Titlefunction DefenderHeroMove (unit)
Timer = Timer+1
  for n, creature in GetDefenderCreatures() do
    local id = GetCreatureType(creature)
    if id == CREATURE_ARCHER then
     local targets = GetAttackerCreatures()
     chosen_target = targets[random(length(targets)+1)]
    end
  end
commandShot (creature, chosen_target, nil)

}{0TT@6bI4
Hello,
I have a couple of questions about your script: there cannot be a creature with the name "Priest" on the battlefield, just as there cannot be Osillian (if this is a variable that stores the correct name, then it's okay, but if you forgot the quotes, then read on)
All creatures have a composite script name in the form "coordinates+id+number", and this name is stored in the first argument of the hook. In your case, this is the variable unit. And "Priest" and "Osillian" are not on the battlefield.

Write a hook for the turn of the defending hero, and inside it, make a check:
for n, creature in GetDefenderCreatures() do
local id = GetCreatureType(creature)
if id == CREATURE_ARCHER then
local targets = GetAttackerCreatures()
chosen_target = targets[random(length(targets)+1)]
-- actions with the archer creature and the target chosen_target
end
end

The random function needs to be rewritten, as the standard one does not work. You can take the randomizer from Echoes of the Void by RedHeavenHero, if he doesn't mind, or write it yourself.

Attachments 1
1 file attached • Total size: 230.3 KB
User Avatar
Auto-translated
In RedHeavenHero's randomizer, the random function is only created upon initialization of the randomizer, i.e., when the InitRandom() function is called. You need to add this line to the beginning of the script.

Perhaps, summoning skill is required to cast the heavenly shield?
I have encountered a situation where I cannot cast masscare without light magic.
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
In reply to }{0TT@6bI4
User Avatar
Auto-translated

Yes, indeed, with the expert call, the Celestial Shield began to be cast. And the random function also started generating numbers. But now, this problem has arisen: the script is complaining about the second argument of your function, i.e., the variable chosen_target (screenshot attached). Maybe I misunderstood it somehow and, accordingly, I'm writing it incorrectly?

P.S. Everything was resolved; I just needed to add a sleep command so that everything would work correctly. Thank you very much.

The function itself:

Titlefunction DefenderHeroMove (unit)
InitRandom()
for n, creature in GetDefenderCreatures() do
local id = GetCreatureType(creature)
if id == CREATURE_ARCHER then
local targets = GetAttackerCreatures()
local chosen_target = targets[random(length(targets)+1)]
commandShot (creature, chosen_target, nil)
end
end
}{0TT@6bI4
In the randomizer from RedHeavenHero, the random function is created only after the randomizer is initialized, i.e., after calling the InitRandom() function. You need to add this line to the beginning of the script.

Perhaps, a summoning skill is required to cast the Celestial Shield?
I have encountered the issue where I cannot cast Masscare without Light Magic.
Attachments 1
1 file attached • Total size: 224.5 KB
In reply to Min_Carolin
User Avatar
Auto-translated

There are still some problems. During a hero's turn, instead of performing the action once, the archer starts shooting a huge number of times without stopping until the ammunition runs out. I can't figure out how to stop it.

Here's the script again:

Titlefunction DefenderHeroMove (unit)
InitRandom()
for n, creature in GetDefenderCreatures() do
local id = GetCreatureType(creature)
if id == CREATURE_ARCHER then
local targets = GetAttackerCreatures()
chosen_target = targets[random(length(targets)+1)]
sleep (50)
commandShot (creature, chosen_target, not nil)
sleep (1)
end
end

Min_Carolin

Yes, indeed, with the expert call, Heavenly Shield started to be cast. And random also started to generate numbers. But now there is such a problem: the script complains about the second argument of your function, i.e., the variable chosen_target (screenshot attached). Maybe I misunderstood it somehow and, accordingly, I'm writing it incorrectly?

P.S. Everything was resolved; I just needed to add sleep so that everything would work correctly. Thank you very much.

The function itself:

Titlefunction DefenderHeroMove (unit)
InitRandom()
for n, creature in GetDefenderCreatures() do
local id = GetCreatureType(creature)
if id == CREATURE_ARCHER then
local targets = GetAttackerCreatures()
local chosen_target = targets[random(length(targets)+1)]
commandShot (creature, chosen_target, nil)
end
end

User Avatar
Auto-translated
Hello. I have the following idea: a hero enters a region (there are several, as well as heroes), and he is asked a question. If he agrees, certain actions are triggered in that region (for example, it is blocked until something happens). I planned to create lists of these "activated" regions, as well as the heroes who activated them, filling them into arrays and then clearing the entries from the lists (so that later they could be activated again by the same hero, or another hero) when the actions in the region are completed, but unfortunately, I don't know how to implement this.
User Avatar
Auto-translated

When initializing each region in the list, a function is created on the spot for it, which will be called by the trigger. For the function, the name of the region is written into a local variable using upvalues. After that, you can perform any actions with the region's name (and, accordingly, its properties) and the hero.

regions = {
list = {
["Region123"] = {active=nil, activator=nil},
...
},

init = function()
for region, props in regions.list do
regions.list[region].enter = function(hero)
local reg = %region
regions.list[reg].active = 1
regions.list[reg].activator = hero
-- Actions with the region, access to whose properties can be found by the local name reg
end
Trigger(REGION_ENTER_AND_STOP_TRIGGER, region, "regions.list['"..region.."'].enter")
end
end,
}

regions.init()
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
In reply to }{0TT@6bI4
User Avatar
Auto-translated
My problem is as follows. There is a code whose purpose is to prioritize capturing dwellings for the AI through a thread. Everything works perfectly, except for one thing. If one of the AI heroes settles in a Castle, the thread crashes. The crash frequency can be reduced by 100 times by adding an IsHeroInTown check, but the crash still occurs on weeks 2-3, even when the check passes successfully, and at that moment the hero settles in the Castle. This check also slows down the thread, so I am looking for other options. Is it possible to somehow track the crash and restart the thread? Are there any more interesting ideas?
--global_creature_arrays--------------------------------------------------------
CnogradeID = {};--non-upgrade_creature_IDs_(tier_1-7)
CnogradeID[0] = { 1, 3, 5, 7, 9, 11, 13};--haven
CnogradeID[1] = { 43, 45, 47, 49, 51, 53, 55};--sylvan
CnogradeID[2] = { 57, 59, 61, 63, 65, 67, 69};--academy
CnogradeID[3] = { 71, 73, 75, 77, 79, 81, 83};--dungeon
CnogradeID[4] = { 29, 31, 33, 35, 37, 39, 41};--necropolis
CnogradeID[5] = { 15, 17, 19, 21, 23, 25, 27};--inferno
CnogradeID[6] = { 92, 94, 96, 98,100,102,104};--fortress
CnogradeID[7] = {117,119,121,123,125,127,129};--stronghold
--
Cgrade1ID = {};--first_upgrade_creature_IDs_(tier_1-7)
Cgrade1ID[0] = { 2, 4, 6, 8, 10, 12, 14};--haven
Cgrade1ID[1] = { 44, 46, 48, 50, 52, 54, 56};--sylvan
Cgrade1ID[2] = { 58, 60, 62, 64, 66, 68, 70};--academy
Cgrade1ID[3] = { 72, 74, 76, 78, 80, 82, 84};--dungeon
Cgrade1ID[4] = { 30, 32, 34, 36, 38, 40, 42};--necropolis
Cgrade1ID[5] = { 16, 18, 20, 22, 24, 26, 28};--inferno
Cgrade1ID[6] = { 93, 95, 97, 99,101,103,105};--fortress
Cgrade1ID[7] = {118,120,122,124,126,128,130};--stronghold
--
Cgrade2ID = {};--second_upgrade_creature_IDs_(tier_1-7)
Cgrade2ID[0] = {106,107,108,109,110,111,112};--haven
Cgrade2ID[1] = {145,146,147,148,149,150,151};--sylvan
Cgrade2ID[2] = {159,160,161,162,163,164,165};--academy
Cgrade2ID[3] = {138,139,140,141,142,143,144};--dungeon
Cgrade2ID[4] = {152,153,154,155,156,157,158};--necropolis
Cgrade2ID[5] = {131,132,133,134,135,136,137};--inferno
Cgrade2ID[6] = {166,167,168,169,170,171,172};--fortress
Cgrade2ID[7] = {173,174,175,176,177,178,179};--stronghold
--
Cgrowth = {};--creature_weekly_growth_modifier_(1_weekly_growth+( special_building_growth)/2))
Cgrowth[0] = { 24, 12, 10, 5, 3, 2, 1};--haven
Cgrowth[1] = { 12, 9, 7, 4, 3,2.5, 1};--sylvan
Cgrowth[2] = { 20, 14, 9, 5, 4, 2, 1};--academy
Cgrowth[3] = { 8, 6, 6, 4, 3, 2, 1};--dungeon
Cgrowth[4] = { 23, 15, 9, 5, 3, 2,1.5};--necropolis
Cgrowth[5] = { 16, 16, 8, 5,3.5, 2, 1};--inferno
Cgrowth[6] = { 18, 14, 7, 8,3.5, 2, 1};--fortress
Cgrowth[7] = { 28, 13, 11, 5, 5, 2, 1};--stronghold
--
Cpower = {};--average_power_of_1_weekly_growth_of_units_from_tie r_1_to_tier_7
Cpower[1] = {1100,1700,2000,2600,3300,4300,4850};--non-upgraded
Cpower[2] = {1800,2400,2900,3500,4500,5000,6000};--upgraded
Cpower[3] = {1800,2400,2900,3500,4500,5000,6000};--upgraded
--
Cgradetype = {CnogradeID,Cgrade1ID,Cgrade2ID};--upgrade_type_identifier
--
function GetArmyPower(OBJ)
local VALUE = 0;
for i = 1,3 do--creature_upgrade_type
for j = 0,7 do--creature_race
for k = 1,7 do--creature_tier
if GetObjectCreatures(OBJ,Cgradetype[j][k]) > 0 then
VALUE = VALUE + ceil(GetObjectCreatures(OBJ,Cgradetype[j][k])/Cgrowth[j][k]*Cpower[k]);
end;
end;
end;
end;
return VALUE;
end;
--dwelling_AI_attraction--------------------------------------------------------
function AIAttractionLoop(PLAYER)
if GetPlayerRace(1) == GetPlayerRace(2) then--if_players'_race_is_the_same
while 1 do
for i = 1,2 do--dwelling_side
for j = 1,4 do--dwelling_levels
if GetObjectOwner("Dwel"..j.."P"..i) ~= PLAYER then
SetAIPlayerAttractor("Dwel"..j.."P"..i,PLAYER,1);--set_dwelling_attractor
else
SetAIPlayerAttractor("Dwel"..j.."P"..i,PLAYER,-1);--attractor_cancel
end;
end;
end;
sleep(5);
end;
else--if_players'_race_isn't_the_same
while 1 do
local AIheroes = GetPlayerHeroes(PLAYER);
local ln = length(AIheroes);
for i = 0,ln-1 do--quantity_of_AI_heroes
for j = 1,2 do--dwelling_side
for k = 1,4 do--dwelling_levels
if GetObjectOwner("Dwel"..k.."P"..j) ~= PLAYER then
if GetArmyPower(AIheroes) > GetArmyPower("Dwel"..k.."P"..j.."Gar")*2 then
SetAIHeroAttractor("Dwel"..k.."P"..j,AIheroes,1);--set_dwelling_attractor
end;
else
SetAIHeroAttractor("Dwel"..k.."P"..j,AIheroes,0);--attractor_cancel
end;
end;
end;
end;
sleep(5);
end;
end;
end;
--
if IsAIPlayer(1) == 1 then
startThread(AIAttractionLoop,1);
elseif IsAIPlayer(2) == 1 then
startThread(AIAttractionLoop,2);
end;
Attachments 1
1 file attached • Total size: 4.9 KB
In reply to Долгий
User Avatar
Auto-translated
Done. I just needed to launch a separate thread that runs the AIAttractionLoop function, in which I removed the while loops. Even if the function crashes due to a hero getting stuck in a town, the new thread continues to launch it.
Auto-translated
Good evening, I created a function to increase a hero's level, and I can't figure out what to write in the "level up hero" part so that it increases the level of the hero who touched the object. Everything else works, except for the "level up hero" part. ``` function OPIT() number = GetCurrentPlayer() Gold = GetPlayerResource(number, 6) if Gold >= 6000 then QuestionBoxForPlayers(number, "Maps/Multiplayer/JoyPatriot/Teks/Vopros.txt", "yes", "no") else MessageBoxForPlayers(number, "Maps/Multiplayer/JoyPatriot/Teks/OP.txt", nil) end end function yes() number = GetCurrentPlayer() SetPlayerResource(number, 6, Gold - 6000) LevelUpHero(hero) end SetObjectEnabled("OP", nil); Trigger(OBJECT_TOUCH_TRIGGER, "OP", "OPIT");
User Avatar
Auto-translated
A brief overview. `hero` is a variable. In order for something to be stored in it, something needs to be assigned to it! This is done by manually declaring the variable, or the game will assign something to it through its actions. To do this, arguments are specified in the sub-trigger function (the list is in the developer's manual under the Trigger function). That is:
function Test(hero)
if hero == "..." then

end
end
Trigger(OBJECT_TOUCH_TRIGGER, ...).

In your case, the code needs to be changed as follows:
function OPIT(hero)
number = GetCurrentPlayer() --I recommend replacing this with number=GetObjectOwner(hero)
local Gold = GetPlayerResource(number,6) --It's better to keep the variable local
if Gold >= 6000 then
QuestionBoxForPlayers(number,"Maps/Multiplayer/JoyPatriot/Teks/Vopros.txt", "yes([["..hero.."]])", "no")
else MessageBoxForPlayers(number,"Maps/Multiplayer/JoyPatriot/Teks/OP.txt", nil)
end
end

function yes(hero)
number = GetCurrentPlayer() --The same. It's better to use number=GetObjectOwner(hero)
local Gold = GetPlayerResource(number) --There's nothing wrong with repeating the operation, although it could be done better; but the main thing is that the error of overwriting something in the Gold variable has been eliminated
SetPlayerResource(number,6,Gold-6000)
LevelUpHero(hero)
return parse '' --We remove the machine error, which has no effect. Otherwise, a warning will be spammed in the console
end

SetObjectEnabled("OP",nil);
Trigger(OBJECT_TOUCH_TRIGGER,"OP","OPIT");

P.s. I recommend giving variables meaningful names. And objects too. For example, "ExperienceStone" and "ExperienceStoneTouch", respectively...

С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
Auto-translated

Thank you, I understand now.

But now, for some reason, messages have stopped displaying for one of the four players, and only display for the red or blue player. In other words, before, my script would only display a message to the player who touched the object, but now it only displays it to the red or blue player. If the green or orange player touches it, the message is sent to both the red and blue players simultaneously.

User Avatar
Auto-translated
Add `print(number, ", ", hero, ", ", GetObjectOwner(hero))` before the messages and tell me what it outputs when the units touch...
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
In reply to }{0TT@6bI4
Auto-translated
}{0TT@6bI4
Add print(number, ", ", hero, ", ", GetObjectOwner(hero)) before the messages and tell me what it outputs when they touch...


It outputs:

for the first one - 1, Calid, 1

for the second one - 2, Sarge, 2

for the third one - 3, Mardigo, 3
And for the 4th player, respectively

User Avatar
Auto-translated
I think the issue is that the green and orange players are AI-controlled. And, I assume, in my case, everything works correctly, and the MessageBoxForPlayers message for AI players is simply redirected to the human players. But in your case... we'll find out. Leave the print, but in the number variable, revert to your old formula for calculating the player number.
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________

Statistics

Welcome our newest member: Emil