Spawning through script

From Mod Wiki

(Difference between revisions)
Jump to: navigation, search
Revision as of 20:52, 4 July 2008 (edit)
Don Reba (Talk | contribs)

← Previous diff
Revision as of 00:47, 5 July 2008 (edit) (undo)
Soduka (Talk | contribs)

Next diff →
Line 3: Line 3:
==Theory== ==Theory==
-There is a single script function responcible for spawning objects:+There is a single script function responsible for spawning objects:
<source lang="lua"> <source lang="lua">
alife():create(section, position, levelvertex, gamevertex) alife():create(section, position, levelvertex, gamevertex)
Line 36: Line 36:
Why <tt>1</tt>, not <tt>level_vertex</tt>? We checked and found not significant difference which <tt>level_vertex</tt>, although in some cases a valid vertex is required; without it an object might spawn somewhere other than planned... But in most cases it is ok to specify <tt>1</tt>. Why <tt>1</tt>, not <tt>level_vertex</tt>? We checked and found not significant difference which <tt>level_vertex</tt>, although in some cases a valid vertex is required; without it an object might spawn somewhere other than planned... But in most cases it is ok to specify <tt>1</tt>.
-(Ignoring level_vertex may cause spawned objects to fall through the gound.)+(Ignoring level_vertex may cause spawned objects to fall through the ground.)
Now, <tt>game_vertex</tt> determines everything — it specifies which the level the object will be spawned on, and so is necessary. Theoretically, one could find one <tt>game_vertex</tt> for each level and use them in scripts. Now, <tt>game_vertex</tt> determines everything — it specifies which the level the object will be spawned on, and so is necessary. Theoretically, one could find one <tt>game_vertex</tt> for each level and use them in scripts.
In reality, <tt>game_vertex</tt> shows which fragment of the map will be used (the whole map is divided into segments numbered across all levels, and <tt>game_vertex</tt> chooses the right one), so incorrect usage is dangerous... In reality, <tt>game_vertex</tt> shows which fragment of the map will be used (the whole map is divided into segments numbered across all levels, and <tt>game_vertex</tt> chooses the right one), so incorrect usage is dangerous...
Line 68: Line 68:
</source> </source>
-:''By the way, <tt>create_ammo</tt> is practically the same thing. The difference is that <tt>create_ammo</tt> is meant specifically for spawning ammo, and allows creation of half-full boxes. There might be some other differences. It should be noted that the game authors themselves spawn bullets exclusively with <tt>create_ammo</tt>. [[User:Imp]] 22:38, 23 July 2007 (EEST)''+:''By the way, <tt>create_ammo</tt> is practically the same thing. The difference is that <tt>create_ammo</tt> is meant specifically for spawning ammo, and allows creation of half-full boxes. There might be some other differences. It should be noted that the game authors themselves spawn bullets exclusively with <tt>create_ammo</tt>. [[User:Imp]] 22:38, 23 July 2007 (EST)''
The minimum set is coordinates, ID, section, while the server objects is usually useful only for the ID, since the ID could be used to get that very server object: The minimum set is coordinates, ID, section, while the server objects is usually useful only for the ID, since the ID could be used to get that very server object:
Line 77: Line 77:
It could be used, for example, to leave a marker, but I use it for other goals — spawning complex variables — NPCs. It could be used, for example, to leave a marker, but I use it for other goals — spawning complex variables — NPCs.
-Now, try to solve the following problem — create a mercenary, change his faction, change his inventory, and make him friedly towards the player.+Now, try to solve the following problem — create a mercenary, change his faction, change his inventory, and make him friendly towards the player.
At a certain moment, the spawned object enters online mode; at that moment the callback <tt>net_spawn</tt> is fired. At a certain moment, the spawned object enters online mode; at that moment the callback <tt>net_spawn</tt> is fired.
Line 92: Line 92:
And so, we catch our killer by ID. And so, we catch our killer by ID.
-The rest is simple — call functions for spawning a guass with ammo for it in the NPC's inventory (see above), change his faction with a special function, make him friendly.+The rest is simple — call functions for spawning a Gauss with ammo for it in the NPC's inventory (see above), change his faction with a special function, make him friendly.
Why so complicated? Simply, the NPC does not exist in offline mode. There is only an indirect mention of him and, in addition, all of those functions with "NPC" objects, not with server objects. Why so complicated? Simply, the NPC does not exist in offline mode. There is only an indirect mention of him and, in addition, all of those functions with "NPC" objects, not with server objects.
Line 111: Line 111:
Now, lets make a quest. Now, lets make a quest.
-'''Problem:''' after speaking with Sidorovich, spawn a zomby at the plant in the first location. <!--Для того, чтобы не повредить оригинальный сюжет игры, задание будет выдаваться '''после''' прохождения квеста с флешкой Шустрого, так как появись там зомби одновременно с бандитами и Шустрым... я думаю, исход боя предрешен :)-->+'''Problem:''' after speaking with Sidorovich, spawn a zombie at the plant in the first location. <!--Для того, чтобы не повредить оригинальный сюжет игры, задание будет выдаваться '''после''' прохождения квеста с флешкой Шустрого, так как появись там зомби одновременно с бандитами и Шустрым... я думаю, исход боя предрешен :)-->
'''Implementation:''' I will try to describe everything thoroughly, step by step. First, run the game. :) '''Implementation:''' I will try to describe everything thoroughly, step by step. First, run the game. :)
Line 126: Line 126:
To exit <tt>demo_record</tt> mode, press Esc and enter <tt>rs_stats off</tt> or <tt>rs_stats 0</tt> in the console (remove information display). To exit <tt>demo_record</tt> mode, press Esc and enter <tt>rs_stats off</tt> or <tt>rs_stats 0</tt> in the console (remove information display).
-:''Another way of getting this same information is to walk to the proper place and run the following script, shich will give you the proper coordinates. I run it with the well-known method through main_menu:''+:''Another way of getting this same information is to walk to the proper place and run the following script, which will give you the proper coordinates. I run it with the well-known method through main_menu:''
<source lang="lua"> <source lang="lua">
function main_menu:main_cheat_f3() function main_menu:main_cheat_f3()
Line 172: Line 172:
</source> </source>
-This means that our fifth zombie will enherit all parameters of zombie_strong. We only add a visual appearance.+This means that our fifth zombie will inherit all parameters of zombie_strong. We only add a visual appearance.
Writer further: Writer further:
Line 223: Line 223:
That's it. Save and close the file. That's it. Save and close the file.
-Continuing the ducussion :) 
-To make sure that the game does nto crash after we add a new type of monsteres, we must add them to the file xr_statistic.script. So, copy this file from the scrips foolder of the game into our folder alongside esc_zombie.script and open it for editing.+----
 + 
 +Continuing the discussion :)
 + 
 +To make sure that the game does not crash after we add a new type of monster, we must add them to the file xr_statistic.script. So, copy this file from the scrips folder of the game into our folder alongside esc_zombie.script and open it for editing.
Add to <tt>local killCountProps</tt> to monsters the line: Add to <tt>local killCountProps</tt> to monsters the line:
Line 262: Line 265:
All correct — the game does not know which icon to show for the zombie. Monster icons are stored in the file ui_npc_monster.dds. Here we have to alternatives: All correct — the game does not know which icon to show for the zombie. Monster icons are stored in the file ui_npc_monster.dds. Here we have to alternatives:
-* If you are friends with Photoshop, edit this file (paint and add icons).+* If you are friends with Photoshop, edit this file (paint and add icons). (Tutorial on editing Stalker UI.dds files in Wiki)
-* Take an existing one from any mod, with the author's permission, of course. Right now we will skip this step and give our zombie the controller's icon :)+* Take an existing one from any mod, with the author's permission, of course. Right now we will skip this step and give our zombie the controller's icon.
Return to file m_zombie.ltx and into the middle of the [m_zombie_e]:monster_base section add the parameter: Return to file m_zombie.ltx and into the middle of the [m_zombie_e]:monster_base section add the parameter:
Line 403: Line 406:
* Create in folder gamedata folder meshes and in it folder monsters, and there folder zombi. In the meshes folder models for characters, objects, and environment objects from the game are kept. As I said above, there are 5 zombie models in the game, but 6 textures. The numbering is also a little confusing — 1, 2, 4... where is the third? Must have ran away. :) * Create in folder gamedata folder meshes and in it folder monsters, and there folder zombi. In the meshes folder models for characters, objects, and environment objects from the game are kept. As I said above, there are 5 zombie models in the game, but 6 textures. The numbering is also a little confusing — 1, 2, 4... where is the third? Must have ran away. :)
-* Copy from the folder with the original game files into the one we created file zombi_2.ogf and rename it into zombi_3.ogf. Open fhe file of our model with your favourite hex editor (I use Binary Editor 1.00). Since this article is targeted not only at advanced users, but also beginnners that want to make something, I won't bore you with adresses, byte notation, etc, but will simply show you what to edit :)+* Copy from the folder with the original game files into the one we created file zombi_2.ogf and rename it into zombi_3.ogf. Open fhe file of our model with your favorite hex editor (I use Binary Editor 1.00). Since this article is targeted not only at advanced users, but also beginners that want to make something, I won't bore you with addresses, byte notation, etc, but will simply show you what to edit :)
[http://www.golushkov.pp.net.ua/photo/11-0-717-3 Model file '''before''' editing] [http://www.golushkov.pp.net.ua/photo/11-0-717-3 Model file '''before''' editing]
Line 409: Line 412:
[http://www.golushkov.pp.net.ua/photo/11-0-718-3 Model file '''after''' editing] [http://www.golushkov.pp.net.ua/photo/11-0-718-3 Model file '''after''' editing]
-You can see on these screns that we have simply edited the texture path for this model. That's it. Without using a 3D editor and spending a lot of time, we get a brand new mmodel (or so it would seem). :)+You can see on these screens that we have simply edited the texture path for this model. That's it. Without using a 3D editor and spending a lot of time, we get a brand new model (or so it would seem). :)
-'''5.''' Now we add our zombie to all files we created earlker. To the file m_zombie.ltx we add at the very end the section:+'''5.''' Now we add our zombie to all files we created earlier. To the file m_zombie.ltx we add at the very end the section:
<source lang="ini"> <source lang="ini">
[zombie_old]:zombie_normal [zombie_old]:zombie_normal
Line 519: Line 522:
==Spawning NPC== ==Spawning NPC==
-:''This part is written by user [[User:Arhet|Arhet]] and is modelled after the way the NPC faction "Sin" is implemented in the SRP Mod.''+:''This part is written by user [[User:Arhet|Arhet]] and is modeled after the way the NPC faction "Sin" is implemented in the SRP Mod.''
Use files: Use files:

Revision as of 00:47, 5 July 2008

Contents


Theory

There is a single script function responsible for spawning objects:

alife():create(section, position, levelvertex, gamevertex)
Strictly speaking, there are two: create and create_ammo, but the differences between them are minimal. Imp 22:45, 23 июля 2007 (EEST)

The first parameter — ltx section describing the object. For instance: "bolt", "med_kit" — are simple sections, simple objects. There are also objects that move between online and offline modes; these are NPCs, monsters, etc. For instance: mil_killer_respawn_2 — spawns a killer sniper.

I guess, position needs no explanation, except one nuance: height is Y, not Z. Position can be created with vector():set(x,y,z), where x, y, and z are coordinates of a point in the level in which we are spawning the object.

Further on it gets complicated and difficult for me to describe.

Lets move from the simple to the complex. Each level contains many objects. All objects consist of polygons, each polygon contains vertices.

This is what we must specified. I do not really understand why; most likely for precise positioning of objects. For example, you can get the vertex nearest to an actor — db.actor:level_vertex().

The next parameter is much more interesting; game_vertex is almost the same thing as level_vertex, except (!) that it is a global value! Whereas level_vertex is calculated for the level, game_vertex is for the whole game, and is necessary to indicate which map to spawn the object on (I could not come up with a more sensible explanation).

Correspondingly, to spawn an object on a different map, it is enough to set game_vertex in the fourth parameter. For example:

db.actor:game_vertex()

And so, to spawn, for instance, a blot under an actor's feet, we write:

alife():create("bolt", db.actor():position(), 1, db.actor:game_verte())

Why 1, not level_vertex? We checked and found not significant difference which level_vertex, although in some cases a valid vertex is required; without it an object might spawn somewhere other than planned... But in most cases it is ok to specify 1. (Ignoring level_vertex may cause spawned objects to fall through the ground.) Now, game_vertex determines everything — it specifies which the level the object will be spawned on, and so is necessary. Theoretically, one could find one game_vertex for each level and use them in scripts. In reality, game_vertex shows which fragment of the map will be used (the whole map is divided into segments numbered across all levels, and game_vertex chooses the right one), so incorrect usage is dangerous...

Other than that, there is one additional parameter — ID of the object. If an ID of an NPC or an actor is given, the object will be spawned in his inventory.

For example (spawn artifact Medusa in an actor's inventory):

alife():create("af_medusa", db.actor():position(), 1, db.actor:game_vertex(), db.actor:id())

The spawn function returns a server object, not an NPC, or a monster, or anything else.

A server object lets the newly created NPC or a stash be filled with various items. For example, lets create a Duty member in front of the entrance to Sidorovich and give him a box of ammo:
local obj
local a = vector() -- Set variable type
local dir = db.actor:direction()
 
a.x = -243.61	-- X coordinate
a.y = -19.52	-- height Y
a.z = -127.17	-- Z coordinate
 
obj = alife():create("bar_dolg_respawn_3",a,13193,8,65535)
alife():create_ammo("ammo_9x18_fmj",
	obj.position,
	obj.m_level_vertex_id,
	obj.m_game_vertex_id,
	obj.id,
	20) -- number of bullets
By the way, create_ammo is practically the same thing. The difference is that create_ammo is meant specifically for spawning ammo, and allows creation of half-full boxes. There might be some other differences. It should be noted that the game authors themselves spawn bullets exclusively with create_ammo. User:Imp 22:38, 23 July 2007 (EST)

The minimum set is coordinates, ID, section, while the server objects is usually useful only for the ID, since the ID could be used to get that very server object:

alife():object(id)

It could be used, for example, to leave a marker, but I use it for other goals — spawning complex variables — NPCs.

Now, try to solve the following problem — create a mercenary, change his faction, change his inventory, and make him friendly towards the player.

At a certain moment, the spawned object enters online mode; at that moment the callback net_spawn is fired.

What do we do? Compare the online object's ID with the stored ID!

If they coincide, such as:

if obj:id()==saved_id then ...

It is important that the server object has an ID as a parameter, while the online object returns it from a function. This is important, or you might get in trouble.

And so, we catch our killer by ID.

The rest is simple — call functions for spawning a Gauss with ammo for it in the NPC's inventory (see above), change his faction with a special function, make him friendly.

Why so complicated? Simply, the NPC does not exist in offline mode. There is only an indirect mention of him and, in addition, all of those functions with "NPC" objects, not with server objects.

Practice (part 1)

1. To avoid repetition, just study article on quest creation by Fr3nzy; I have seen no better article on the subject. :) Here we will merely tie everything together and learn to spawn objects from a script.

A small aside:

Why is it better to spawn from a script, not from xrSpawner? The xrSpawner application, with all its advantages, has one drawback — it uses the file all.spawn, which leads to:

  • Impossibility of combining two mods using such spawning
  • Necessity of starting the game over each time

The situation when spawning with a script is such: in the overwhelming majority of cases, previously saved games will work, which is good news. :)

Now, lets make a quest.

Problem: after speaking with Sidorovich, spawn a zombie at the plant in the first location.

Implementation: I will try to describe everything thoroughly, step by step. First, run the game. :)

Enter the following command in the console:

rs_stats on or rs_stats 1

This turns on display of information on the screen. Next, enter one more command: demo_record 1

Now, "fly" to the factory. We have to choose a location for spawning objects, and this mode is perfect for it. Set the camera in the location of the planned spawn and record the coordinates. I got 115, -6, -16.

To exit demo_record mode, press Esc and enter rs_stats off or rs_stats 0 in the console (remove information display).

Another way of getting this same information is to walk to the proper place and run the following script, which will give you the proper coordinates. I run it with the well-known method through main_menu:
function main_menu:main_cheat_f3()
	-- output a meessage about our location
	local text
	local vid
	local gvid
	local a = vector() -- Variable type
	local text
 
	a    = db.actor:position()        -- Our position's coordinates
	vid  = db.actor:level_vertex_id() 
	gvid = db.actor:game_vertex_id() 
	text = "Position:\\nX= "..a.x.."\\nY= "..a.y.."\\nZ= "..a.z.."\\nlevel_vertex= "..vid.."\\ngame_vertex_id= "..gvid
	news_manager.send_tip(db.actor, text, nil, nil, 30000)
end
As a result, you need not experiment, and get everything, including level_vertex and game_vertex. Imp 22:38, 23 July 2007 (EEST)

Exit the game, go to the folder in which the game is installed, create the gamedata folder (assuming the mod is created over a clean game, with no other mods, and have the unpacked resourced in some folder, such as gamedata source).

Create folder config in gamedata, in it — folder creatures. Copy file m_zombie.ltx from the original folder and open it for editing.

There are 5 models of zombies in the game files, in files: files zombi_1.ogf, zombi_1_ghost.ogf, zombi_2.ogf, zombi_trup.ogf, zombi_trup_2.ogf.

Lets return them all into the game. :)

We already have sections: [zombie_weak]:m_zombie_e, [zombie_normal]:m_zombie_e, [zombie_strong]:m_zombie_e и [zombie_immortal]:zombie_strong.

The last two types use the same model zombi_trup.ogf, hm... not right, fix this. The section should look like this:

[zombie_immortal]:zombie_strong
$spawn          = "monsters\zombies\zombie_immortal"
visual          = monsters\zombi\zombi_trup_2
panic_threshold = 0.0

Add the fifth model.

To achieve this, create the following section at the end of the file:

[zombie_ghost]:zombie_strong

This means that our fifth zombie will inherit all parameters of zombie_strong. We only add a visual appearance.

Writer further:

$spawn = "monsters\zombies\zombie_ghost"
visual = monsters\zombi\zombi_1_ghost

That's it. Save all changes and close the file.

2. Writing the spawn script. Create folder scripts in folder gamedata, in it create a new text document and name it esc_zombie.script.

Third aside:

During the writing of the article the original zombie_stori.script from horror-mod was used. The spawn concept has been carried over practically unaltered, therefore I certainly have no claim to the authorship of this method. :)

So, open our empty file for editing, in the first line declare a variable for storing our zombie:

local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", "zombie_ghost"}

Next, write the function:

function spawn_zombies( position, total )
	local zombie_index                       -- zombie type from zombie_types array
	local new_pos, x_offset, z_offset        -- declare variables
	for zombie_index=1, total do             -- spin the loop the number of times given by the variable "total"
		x_offset = math.random(5)        -- random x between 1 and 5
		z_offset = math.random(5)        -- random z between 1 and 5
		new_pos = position               -- transfer the coordinates to a function
		new_pos.x = new_pos.x + x_offset -- add the random x to the x coordinate
		new_pos.z = new_pos.z + z_offset -- add the random z to the z coordinate
		-- below we call the function of random zombie spawn itself for zombie_types[math.random(5)] tied to our coordinates
		alife():create(zombie_types[math.random(5)], new_pos, db.actor:level_vertex_id(), db.actor:game_vertex_id())
	end
end

And lastly:

function zomby_story_1( actor, npc )
-- ten zombies at the plant
	local spawn_point = vector():set( 115, -6, -16 ) -- here we specify the coordinates we got while "flying"
	spawn_zombies( spawn_point, 10 )                 -- here is the call of the previous function itself, giving it the coordinates and the number of objects
end

That's it. Save and close the file.



Continuing the discussion :)

To make sure that the game does not crash after we add a new type of monster, we must add them to the file xr_statistic.script. So, copy this file from the scrips folder of the game into our folder alongside esc_zombie.script and open it for editing.

Add to local killCountProps to monsters the line:

zombie_weak = 1, zombie_normal = 2, zombie_strong = 3

To local sect_alias the line:

zombie_weak = "zombie_weak", zombie_normal  = "zombie_normal", zombie_strong = "zombie_strong"

To monster_classes below the line:

[clsid.zombie_s] = "zombie"

To function getNpcType(npc) we add:

elseif npc:character_community() == "zombie" then
	community = "zombie"

Save changes and close the file.

Everything will work great, until we try to loot a killed zombie. The moment we do this, the game will crash with an error like this:

Expression    : fatal error
Function      : CInifile::r_string
File          : D:\xray-svn\xrCore\Xr_ini.cpp
Line          : 351
Description   : <no expression>
Arguments     : Can't find variable icon in [zombie_weak]

All correct — the game does not know which icon to show for the zombie. Monster icons are stored in the file ui_npc_monster.dds. Here we have to alternatives:

  • If you are friends with Photoshop, edit this file (paint and add icons). (Tutorial on editing Stalker UI.dds files in Wiki)
  • Take an existing one from any mod, with the author's permission, of course. Right now we will skip this step and give our zombie the controller's icon.

Return to file m_zombie.ltx and into the middle of the [m_zombie_e]:monster_base section add the parameter:

icon = ui_npc_monster_kontroler

This is it. There will be no more crashes.

3. The current article won't go into detail regarding creation of new dialogues. In the beginning of the article I mentioned a source in which you can find exhaustive information regarding dialogue creation. For instance, article on dialogue creation by BAC9-FLCL.

We merely need to check correctness of the spawn, so I will give you an example only the modified dialog from file dialogs_escape.xml:

<dialog id="escape_trader_talk_info">
	<phrase id="999">
		<text>escape_trader_talk_info_999</text>
		<next>7770</next>
		<next>9991</next>
		<next>9992</next>
		<next>9993</next>
		<next>9994</next>
		<next>9995</next>
		<next>9996</next>
	</phrase>
	<phrase id="9992">
		<text>escape_trader_talk_info_9992</text>
		<next>99922</next>
	</phrase>
	<phrase id="99922">
		<text>escape_trader_talk_info_99922</text>
		<next>9996</next>
		<next>9995</next>
	</phrase>
	<phrase id="9993">
		<text>escape_trader_talk_info_9993</text>
		<next>99933</next>
	</phrase>
	<phrase id="9995">
		<text>escape_trader_talk_info_9995</text>
	</phrase>
	<phrase id="3121">
		<text>escape_trader_talk_info_3121</text>
		<next>9996</next>
		<next>9995</next>
	</phrase>
	<phrase id="3131">
		<text>escape_trader_talk_info_3131</text>
		<next>9996</next>
		<next>9995</next>
	</phrase>
	<phrase id="41">
		<text>escape_trader_talk_info_41</text>
		<next>9996</next>
		<next>9995</next>
	</phrase>
	<!------Our dialog: begin------->
	<phrase id="7770">
		<text>escape_trader_talk_info_7770</text>
		<next>7771</next>
	</phrase>
	<phrase id="7771">
		<text>escape_trader_talk_info_7771</text>
		<next>7772</next>
		<next>7773</next>
	</phrase>
	<phrase id="7772">
		<text>escape_trader_talk_info_7772</text>
		<next>7777</next>
	</phrase>
	<phrase id="7773">
		<text>escape_trader_talk_info_7773</text>
		<next>7779</next>
	</phrase>
	<phrase id="7779">
		<text>escape_trader_talk_info_7779</text>
		<next>9996</next>
		<next>9995</next>
	</phrase>
	<phrase id="7777">
		<text>escape_trader_talk_info_7777</text>
		<action>esc_zombie.zombie_story_1</action>
		<next>9996</next>
		<next>9995</next>
	</phrase>
	<!------Our dialog: end------->
	<phrase id="51">
		<text>escape_trader_talk_info_51</text>
		<next>9996</next>
		<next>9995</next>
	</phrase>
</dialog>

Also,k the file stable_dialogs_escape.xml linked to it. At the very start of the file write the following:

<string id="escape_trader_talk_info_7770">
	<text>Происшествий никаких не было?</text>
</string>
<string id="escape_trader_talk_info_7771">
	<text>Да знаешь... Вроде как тихо все у нас. Хотя, вот, вспомнил! Говорили мне 
на днях, что на фабрике, ну, там, где бандюки околачиваются постоянно, видели какиих-то то ли 
людей, то ли призраков... Мало ли что спьяну почудится - я и сказал этим паникерам, мол, 
закусывать надо! Хех, блин, алкаши...</text>
</string>
<string id="escape_trader_talk_info_7772">
	<text>Дык мне по любому мимо фабрики топать - заодно и посмотрю на этих 
"людей-призраков".</text>
</string>
<string id="escape_trader_talk_info_7773">
	<text>Да я как-то не собирался в ту сторону...</text>
</string>
<string id="escape_trader_talk_info_7779">
	<text>Ну, смотри сам, все равно будь осторожен.</text>
</string>
<string id="escape_trader_talk_info_7777">
	<text>Ага. Сходи, проветрись. Потом зайдешь, расскажешь, что там и как.</text>
</string>
<string id="esc_bridge_soldiers_start_11">
	<text>Здесь проход воспрещён, сталкер.</text>
</string>

This is all. You can start the game, go to Cordon, following the speech with Sidorovich, depending on the choice made, run towards the Plant and ... see for yourself.

the files for this example
Spawn Lib

Homework — return the sixth type of zombie into the game. :)

To be continued...

Practice (part 2)

4. Today we complete the zombie — add their descriptions to the encyclopedia, add icons, work out the "homework". :) I think that if you study this article carefully, you will be able restore any character that has not made it into the final build of the game yourself with script functions. If you have enough time and patience, you can make something like the "night of the living dead" :) — a series of quests connected with the main storyline. So, the "homework" — adding the sixth zombie to the game:

  • Create in folder gamedata folder meshes and in it folder monsters, and there folder zombi. In the meshes folder models for characters, objects, and environment objects from the game are kept. As I said above, there are 5 zombie models in the game, but 6 textures. The numbering is also a little confusing — 1, 2, 4... where is the third? Must have ran away. :)
  • Copy from the folder with the original game files into the one we created file zombi_2.ogf and rename it into zombi_3.ogf. Open fhe file of our model with your favorite hex editor (I use Binary Editor 1.00). Since this article is targeted not only at advanced users, but also beginners that want to make something, I won't bore you with addresses, byte notation, etc, but will simply show you what to edit :)

Model file before editing

Model file after editing

You can see on these screens that we have simply edited the texture path for this model. That's it. Without using a 3D editor and spending a lot of time, we get a brand new model (or so it would seem). :)

5. Now we add our zombie to all files we created earlier. To the file m_zombie.ltx we add at the very end the section:

[zombie_old]:zombie_normal
$spawn = "monsters\zombies\zombie_old"
visual = monsters\zombi\zombi_3

In the file esc_zombie.script we change the array in the first line:

local zombie_types = {"zombie_weak", "zombie_normal", "zombie_strong", "zombie_immortal", 
"zombie_old", "zombie_ghost"}

In function spawn_zombies we modify the spawning line:

alife():create(zombie_types[math.random(6)],new_pos,
db.actor:level_vertex_id(),db.actor:game_vertex_id())

In function zombie_story_1 change the number of objects to a multiple of 6 (not necessary):

spawn_zombies( spawn_point, 12 )

That's it. Save and close.

6. Copy into the folder gamedata\config\gameplay\ the file encyclopedia_mutants.xml, add the description of the zombie to the encyclopedia:

<!-------------------------------- Zombieg ----------------------------->
<article id="mutant_zombieg_general" name="Zombieg" group="Mutants">
	<texture>ui_npc_monster_zombieg</texture>
	<text>enc_mutant_zombieg_general</text>
</article>

To the linked file string_table_enc_mutants.xml in folder gamedata\config\text\rus\ add:

<string id="Zombie">
	<text>Зомби, гражданский</text>
</string>
<string id="Zombieg">
	<text>Зомби-призрак, гражданский</text>
</string>
<string id="enc_mutant_zombieg_general">
	<text>Зомби-привидение отличается от обычного зомби лишь тем, что 
воздействие Выжигателя мозгов полностью разрушило не только структуру личности, но и 
тело, поэтому зомби-призрак несколько более живуч по сравнению с обычным зомби.</text>
</string>
<string id="enc_mutant_zombie_general">
	<text>Воздействие Выжигателя мозгов полностью разрушает структуру личности, 
оставляя только телесную оболочку.\n\n Побродив немного по Зоне, лишённые разума тела 
начинают превращаться в настоящих зомби. Из рефлексов у них остаются лишь самые примитивные, 
оружие и экипировка скоро приходят в негодность. В результате зомби становятся собой ни чем 
иным, как медлительными полутрупами, которых наличествуют лишь два эффективных раздражителя: 
еда и сон. Зомби совершенно неразборчивы в выборе пищи и питья, поэтому их тела буквально 
пропитаны радиацией и токсинами. Как правило, эти существа бесцельно бродят по Зоне или, 
словно трупы, валяются внутри заброшенных построек. Однако, лишь только зомби почует близкое 
присутствие живого человека, он сразу же пытается атаковать. Умудрённые опытом сталкеры 
стараются обходить эти неуклюжие опустошённые оболочки.</text>
</string>

Copy into the same place the file stable_stable_caption.xml and change 3 lines:

<string id="zombie_normal">
	<text>зомбированный, гражданский</text>
</string>
<string id="zombie_strong">
	<text>зомби-призрак, гражданский</text>
</string>
<string id="zombie_weak">
	<text>зомби, гражданский</text>
</string>

Save changes and close.

7. And lastly — add the icons. I used the ready-made file containing icons for zombies and other "reincarnated" monsters (thanks to Fr3nzy). Simply copy the file ui_npc_monster.dds from the archive into the folder gamedata\textures\ui\, and the file ui_npc_monster.xml — into the folder gamedata\config\ui\. If you want to create your own, read the tutorial modifying textures.

In short, here is what the file ui_npc_monster.xml describes: it sets icon coordinates, located in the file ui_npc_monster.dds, for each monster in the game.

Last stroke. Open the file m_zombie.ltx and in the first section replace the line

icon = ui_npc_monster_kontroler

by:

icon = ui_npc_monster_zombie

In section [zombie_ghost] add the line:

icon = ui_npc_monster_zombieg

Save all changes. This is it.

Here are ready files. Good luck and thank you for your attention. :)

Spawning NPC

This part is written by user Arhet and is modeled after the way the NPC faction "Sin" is implemented in the SRP Mod.

Use files:

  • gamedata\config\gameplay\character_desc_escape.xml
  • gamedata\config\gameplay\npc_profile.xml
  • gamedata\config\creatures\spawn_sections.ltx

Begin with character_desc_escape.xml. I won't describe the meaning of each line, since all of this has been done before me.

Here we create a new character:

<specific_character id="esc_dark_stalker_1" team_default = "1">
	<name>GENERATE_NAME_bandit</name>
	<icon>ui_npc_dark_1</icon>
	<map_icon x="0" y="0"></map_icon>
	<bio>sim_stalker_novice_bio</bio>
 
	<class>esc_dark_stalker_01</class> <!-- this uses our new class -->
	<community>dark_stalker</community> <terrain_sect>stalker_terrain</terrain_sect>
	<money min="200" max="600" infinitive="0"></money>
 
	<rank>198</rank>
	<reputation>-24</reputation>
 
	<visual>actors\dark_stalker\dark_stalker_1</visual>
	<snd_config>characters_voice\human_01\monolith\</snd_config>
	<crouch_type>-1</crouch_type>
	<panic_treshold>0</panic_treshold>
	<supplies>
		[spawn] \n
		wpn_dark_colt1911 \n
		ammo_11.43x23_hydro \n
		#include "gameplay\character_items.xml" \n
		#include "gameplay\character_drugs.xml" \n
		#include "gameplay\character_food.xml"
	</supplies>
 
	#include "gameplay\character_criticals_3.xml"
 
	<start_dialog>dm_hello_dialog</start_dialog>
	<actor_dialog>dm_cool_info_dialog</actor_dialog>
</specific_character>

We add our code after some </specific_character>

Now, go to npc_profile.xml and enter:

<character id="esc_dark_stalker_1">
	<class>esc_dark_stalker_01</class>
	<specific_character>esc_dark_stalker_1</specific_character>
</character>

Now, lets go to spawn_section.ltx. The script will "grab" the NPC from this very file. Enter there:

[esc_dark_stalker_1]:stalker ; name of the section for the script
$spawn            = "respawn\esc_dark_stalker_1"
character_profile = esc_dark_stalker_1 ; link to the description of our NPC
spec_rank         = regular ; special rank
community         = dark_stalker ; faction

Now, take any NPC spawn script, substitute the name of the section from spawn_section.ltx and voilà!

Except, the NPC will have default logic (it will wonder about aimlessly). We will get to that later.

Authors

Translation

Personal tools