Skip to content

Posts from Scripts

4.8 (8 ratings)
User Avatar
Auto-translated
Azgalor.
for e, enemy in enemy_creatures do
      for f, friend in friend_creatures do
	 if GetHeroCreatures(heroes, enemy) > 0 and GetHeroCreatures(heroes, enemy) <= 99 then
         reputation = reputation - 1
         sleep(1)
         elseif GetHeroCreatures(heroes, enemy) >= 100 then
         reputation = reputation - 2
         sleep(1)
	 elseif GetHeroCreatures(heroes, friend) > 0 then
         reputation = reputation + 1
            end
         end
      end
end

Let's go through it together with a counter. The first iteration of the e, enemy in enemy creatures loop. In it - a loop of 21 iterations (the inner loop f, friend in friend_creatures). The check for the presence of evil creatures takes place inside the inner loop, sorry for the tautology. This means that if there is 1 creature from the "evil" ones, it will perform the same check 21 times until the inner loop ends! That is, for 1 evil creature, as much as 21 reputation is deducted smile Hence, other funny things happen. The solution is that the loops should not be nested, but separate (I think you don't need to show how to separate them; check for evil creatures in the evil loop for, check for good ones - in the good loop for).

There is also a more elegant solution. First, let's create a global table "reputation", through which we will link all variables and tables. Let's put all IDs into one table with named fields:

reputation = {}
reputation.heroes = {'Valeria', 'Laslo'}
reputation.value = 1--Reputation value
reputation.creatures = {
[1] = {id = 1, mode = 'good', rep_decline = {['<100'] = +1, ['>100'] = +2},},
[2] = {id = 2, mode = 'good', rep_decline = {['<100'] = +1, ['>100'] = +2},},
[3] = {id = 101, mode = 'bad', rep_decline = {['<100'] = -1, ['>100'] = -2},},
[4] = {id = 114, mode = 'bad', rep_decline = {['<100'] = -1, ['>100'] = -2},},
[5] = {id = 98, mode = 'bad', rep_decline = {['<100'] = -1, ['>100'] = -2},},
--And so on
}

This way, we can vary the impact on reputation for each individual creature.

function reputation.condition()
for n, hero in reputation.heroes do
  for key, cr_properties in reputation.creatures do
     if GetHeroCreatures(hero, cr_properties.id)>0 and GetHeroCreatures(hero, cr_properties.id)<100 then
       reputation.value = reputation.value + cr_properties.rep_decline['<100']
     elseif GetHeroCreatures(hero, cr_properties.id)>100 then
       reputation.value = reputation.value + cr_properties.rep_decline['>100']
     end
  end
end

With this solution, you don't even need the "good/bad" field, but for clarity, let it be present. Accordingly, through the global table reputation, we create a table of the impact on the reputation of visiting buildings (in the same way); we write a function for triggers that affect all these objects. The keys in the building table fields will not be 1, 2, 3, etc., as above, but the names of the buildings.

reputation.buildings = {
['BuildingName1'] = {rep_decline = +100},
['BuildingName2'] = {rep_decline = -200},
['BuildingName3'] = {rep_decline = +55},
--And so on
}

function reputation.buildings_visit(hero,obj)
  reputation.value = reputation.value + reputation.buildings[obj].rep_decline
end

function reputation.building_triggers()
  for name, prop in reputation.buildings do
    Trigger(OBJECT_TOUCH_TRIGGER, name, 'reputation.buildings_visit')
  end
end

--Let's not forget to call the "hanging" of triggers. It will go automatically for all objects specified in the table
reputation.building_triggers()

Such global tables are needed so that when there are large volumes of scripts, the names of variables do not intersect. If you wish, you can absolutely erase the lines reputation. everywhere above, and everything will work.

С уважением, }{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
I would like to ask if there is a file that contains the IDs of the creatures from the Tribes of the East faction.
User Avatar
Auto-translated
Alinksolo, open the folder GameFolder/data/data.pak/, and copy the types.xml file to a safe location (it's located outside of any folders, directly within the archive). Open it and press Ctrl + F, then search for CREATURE_PEASANT. Skip the first match, and after the second, you'll see the CREATURE_PEASANT block, with a "1" at the bottom. That's it, scroll down to the creatures you need; the ID will match the number under the name CREATURE.

Alternatively, in the script editor, press Ctrl + Space and scroll through the list to find the creature IDs; the Russian names will be highlighted in yellow.
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
User Avatar
Auto-translated
}{0TT@6bI4, wow! Thank you very much :) I haven't worked with tables before (because they aren't in the original campaign scenarios), so I didn't know that you could format everything so neatly and beautifully. Also, I'm very grateful for the explanation of the counter error caused by the 'for' loops. I knew it was a bad idea to put two 'for' loops with checks of the creature arrays together, and I wasn't wrong) I don't know why I didn't rewrite them right away, because I had a very good example in the form of a function from mission 5 for Freya in the Hammers of Fate, where rebels switch to the player's side (and there, captured buildings, cities, and recruited heroes are passed). Those loops are also separated there...
User Avatar
Auto-translated
In Lua, you can technically organize something resembling object-oriented programming, but it's unlikely to result in a fully functional "heroic" system. Therefore, you have to settle for using global tables with named fields.
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
Auto-translated
}{0TT@6bI4, sorry, but it's still not very clear to me. After creating a CombatScript, shouldn't I return the MapScript file to the MapScript window? If I should, then unfortunately, it doesn't return. Although I change the path and name there, the editor still resets everything and leaves only the CombatScript. And when I open ..., I don't see MapScript in the window on the left anymore, although ScriptsEditor shows that this file is still in the game folder. Isn't it important which script is specified in the MapScript window? And my second question is, I've seen in other maps that the CombatScript lua and xdb files are located not inside the Maps folder, but outside of it. Why do people do this, and if it's important, how can I do it? ScriptsEditor cannot create a file in my map outside the folder. I tried repacking the map, inserting the files manually, but ScriptsEditor starts complaining about an error, and the editor doesn't load such a map at all.

Added 18 minutes later
The first question is resolved. I saved before the game had a chance to reset the changes, and now everything is fine, MapScript is in place. Thank you.
User Avatar
Auto-translated
You are right, after creating CombatScript.xdb, you need to revert to MapScript.xdb; to do this, in the line with MapScript, enter /Maps/SingleMissions/MapName/MapScript

Creating Lua files outside the root folder is just a whim. It is better to create them directly in it.
С уважением, }{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
I'm completely out of ideas, I don't understand anything anymore. In MapScript, I have the following: geroy = "Raelag"; SetGameVar("Raelag", geroy); print("The main character has been named"); SetHeroCombatScript('Raelag', "/Maps/SingleMissions/Koto_Map_New/CombatScript.xdb#xpointer(/Script)"); print("Combat script launched"); Here, everything seems to be in order, and the console confirms it. In CombatScript, I have the following: geroy = GetGameVar("Raelag"); if GetHeroName(GetAttackerHero()) == geroy then print("if the main character is the aggressor"); SetUnitManaPoints(GetAttackerHero(), 200); print("mana given"); sleep(1) UnitCastAimedSpell(GetAttackerHero(), 4); print("casting"); end; if GetHeroName(GetDefenderHero()) == geroy then print("if the main character is the defender"); SetUnitManaPoints(GetDefenderHero(), 200); print("mana given"); sleep(1) UnitCastAimedSpell(GetDefenderHero(), 4); print("casting"); end; And in tactical mode, the following error appears: Value was NIL when getting global with name 'SetHeroCombatScript'. Attempt to call a nil value. Where is the null value when I seem to have written that geroy = "Raelag"? Help, kind people, please tell me what I need to write here? Do I need to make if GetHeroName a function? Yes, it seems like MapScriptsEditor complains about that. Added 5 minutes ago Or is this, after all, a problem with the game not recognizing the combat script at the specified address? Added 2 minutes ago P.S., yes, I know that commas are missing after sleep here. But they are not missing in the script, and it doesn't even get to sleep.
In reply to Марта
User Avatar
Auto-translated
Martha

SetGameVar("Raelag", geroy);
What kind of magic is this?! It's enough to write main_hero = 'Raelag'. SetGameVar is used to transfer variables from script to script and through campaign missions.
In battle, the hero's name can be easily and simply found using the GetHeroName function, so it can be simplified, and a hook for the start of the battle needs to be added.
function Start()
if GetHeroName(GetAttackerHero()) == 'Raelag' then
print("if the main hero is the attacker");
local mana = GetUntiManaPoints(GetAttackerHero()) --Otherwise, we will leave 200 mana for the player for no reason!
SetUnitManaPoints(GetAttackerHero(), 200);
repeat sleep(1) until GetUntiManaPoints(GetAttackerHero())==200 --Sleep until the mana is added
UnitCastAimedSpell(GetAttackerHero(), 4);
SetUnitManaPoints(GetAttackerHero(), mana); --Return the mana to the amount it was!
print("casting");
elseif GetHeroName(GetDefenderHero()) == 'Raelag' then
print("if the main hero is the attacker");
local mana = GetUntiManaPoints(GetDefenderHero()) --Otherwise, we will leave 200 mana for the player for no reason!
SetUnitManaPoints(GetDefenderHero(), 200);
repeat sleep(1) until GetUntiManaPoints(GetDefenderHero())==200 --Sleep until the mana is added
UnitCastAimedSpell(GetDefenderHero(), 4);
SetUnitManaPoints(GetDefenderHero(), mana); --Return the mana to the amount it was!
print("casting");
end;
end

The script error is very strange, as if your MapScript is also running in battle: there is no such function in tactical mode, and therefore an error occurs. Can you attach both script files? Upload them to Google/Yandex Drive.

С уважением, }{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
Let me try to write your script, and if the error persists, it will make sense to upload it.
Otherwise, I don't really know how to do it, but I'll figure it out if necessary.

I had a theory that the combat script is not placed in the map folder for no reason, based on this thread:
https://forum.heroesworld.ru/showthread. ... &page=60
https://forum.heroesworld.ru/showthread. ... &page=61
"The point is that the full path should not be /Maps/SingleMissions/NewRandomMap21/CombatScript.xdb#xpointer(/Script), but /CombatScript.xdb#xpointer(/Script), meaning the xdb file shouldn't be in the folder at all" (quote).

If the error remains, maybe that's the issue.
And if not, then it's my fault.
Thank you for spending time on me.


Added after 12 minutes
P.S., yes, the error remained. I will try to upload the files now.

Added after 7 minutes
Here:
https://disk.yandex.ru/client/disk/%D0%A1%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D1%8B
User Avatar
Auto-translated
It works perfectly for me with CombatScript inside, and in maps like Mercenaries or Cursed, which I looked at, too 🧐 And please don't tell me that you just repeated all the actions from here => https://forum.heroesworld.ru/showpost.ph ... ount=897 I hope you didn't touch any combat-common.lua files? Because JonnyP's method does work, but there is a simpler option, so we can forget about the option of changing the default script altogether. ```lua function ReturnHeroScript(hero) if hero == "Hero Name" then SetHeroCombatScript(hero, "path to script") end end for i=1, 8 do if GetPlayerState(i)==PLAYER_ACTIVE then Trigger(PLAYER_ADD_HERO_TRIGGER, "ReturnHeroScript") end end ``` This script simply reassigns the combat script to the hero if he is hired again. Convenient? Yes, it is. As for the reason for moving the combat script outside the map archive: The player created the script in Maps/SingleMissions/MapName/, but stubbornly wrote only "/CombatScript.xdb#xpointer(/Script)". So RedHeavenHero advised him to put the script file correctly, in the root directory. Or he could have just written "/Maps/SingleMissions/MapName/CombatScript.xdb#xpointer(/Script)"
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
User Avatar
Auto-translated
The link is broken. Can't you even share files from a disk? mad Upload => Wait for the upload to finish => Click "Share" => Copy the link.
С уважением, }{0TT@6bI4
_________________
Группа картостроителей
Там ответы на вопросы, руководства, гайды и прочее
Discord-сервер "Герои 5: S.T.A.L.K.E.R"
Сервер по модификации "Герои 5: S.T.A.L.K.E.R"
_________________
Auto-translated
I just downloaded my own files using that link, so how can it be broken?
Until today, I didn't need the ability to share files, and I don't see any "share" option in Yandex Disk, I only see "create" and "upload".
Or do I need to install Yandex Disk for this?

Added 3 minutes ago
https://disk.yandex.ru/d/e9ITeouDU9b_NA
What about this?

Added 5 minutes ago
Why, I tried the version with combat-common too.
But experience has shown that putting it in the map folder is pointless, and if you put it in the game folder, other characters' special abilities stop working.
So, I reverted everything and haven't returned to it since.
I didn't touch the default files, I just created a folder in Data, and then when it didn't work, I deleted it.
User Avatar
Auto-translated
Can I see the map itself? Is the path to the map script correctly specified there?
Нет войне.
Auto-translated
Gerter, I wouldn't want to release this heavy and unfinished thing online. But I assure you that the scripts currently available are only the ones I uploaded, and their author is Khottabych, not me. I just generated a small test map, added the same things to it, and the same error occurs there - here is the map: https://disk.yandex.ru/d/Ks0EtQTqTrSgiw That is, I probably made the same mistake on it. The question is, what mistake? Added 4 minutes ago Oh, sorry, I didn't change the map name there. I'll change it now. Added 9 minutes ago Changed it, and the error is gone. https://disk.yandex.ru/d/3ZK6bMV7N0S_lA But Railag still doesn't cast anything... Added 1 minute ago At the same time, the console doesn't even display an error message, it's just silent. Oh, I'm doing something wrong... Added 9 minutes ago And I think I found the error on the large map. My combat script.xdb leads not to combat script.lua, but to map script.lua. I wonder how this happened. I'll go fix it.

Statistics

Welcome our newest member: Emil