PDA

View Full Version : [Entities] How to use keyvalues



the-middleman
03-12-2013, 01:41 PM
What are keyvalues?
Keyvalues are little pieces of information about the entities in your map. Each entity has its own keyvalues. For example many entities have a name with which you can trigger them. Players and monsters have a keyvalue for their health. All entities have an origin-keyvalue which is their position in the map. You can find a list of all keyvalues here (http://zyl.pestermom.com/external/entguide/generic/entity_keyvalues.html).
When you make a map you can set some of these keyvalues for you entities by editing their "properties". You can give them names, custom health or a different rendermode. When you turn off Smartedit by clicking the "Smartedit"-button you can see the actual keyvalues. If you have "Smartedit" turned on, you will not see the real keyvalues but nice and more descriptive property fields such as "Volume (10 = loudest)".

Why should you learn about keyvalues?
Normally when you put an entities in your map they will be very static. They will just stay where they are and do what they are supposed to do. Which is boring because you will end up with the same 1998 HL-gameplay as allways.
With keyvalues you can change the properties of your entities while the map is running and you can exchange, compare and calculate information between the entities. You can teleport entities to any location you want, you can put a players name into a game_text or you can make one monster steal health from another. These are just some of the awesome possibilities with keyvalues.

You have allready seen the list of all available keyvalues. But to make it easier I picked out the most interesting ones for you:

The most interesting keyvalues:
targetname
This may be a little confusing. targetname is the name of your entity. Not its target. For example if you have a func_button then targetname is the name of the button. Not its target.

netname
This is the name of a player. Not the entity name but the name that you choose in the Multiplayer options, that shows up in the scoreboard or when you chat. You can use this to make a door that opens only for players named bob. Or you could make a game_text that says "bob sucks!"

classify
Classes are a kind of teams in Sven Coop. For example all players are in the class Player which means they work together. Zombies are in the class Alien monster. Barneys are in the class Player ally. Click this link (http://zyl.pestermom.com/external/entguide/generic/classify.html) to see all classes.
You can use this to change a monsters side at any time. For example you could make a backstabbing barney that acts all nice when you first meet him but then he shoots you when you least expect it.
If you put players in different classes then they can hurt each other. You can use this to make a deathmatch or team-deathmatch map.

origin
This is the position of the entity in your map. You could can change the origin and thus teleport the entity to another position. Or you could trigger something when your entity reaches a certain position.

velocity
This is the speed and direction of your entity´s movement. You can use this to give players or monsters a little boost in a certain direction.

angles
The angles of your entity. You can use this to rotate any entity you like.

v_angle
This works only for players. It determines the direction a player is looking. You could use this to make a text appear when the player looks up into the clouds. Unfortunately you can not use this to control which direction the player should look.

solid
Determines whether an entity is solid or not. You can make monsters not solid which will have some funny effects.

health
The health of a monster or player. You can heal or hurt people that way. You could also make a room with medical supplies and door that opens only for hurt players. Add a sign: "only for those who need it!"

frags
For monsters this is how many kills it got. For players this is their score which you can see in the score-board. You can use this to change the players score to reward or punish them. You could make a door that opens only for cool players ("You need at least 100 points to enter here"). Or make a game_text that says "5 noobs were killed by the gargantua".

button
What buttons is a player currently pressing? You can trigger something in your map when you press use. Or when you walk backward. Or jump.

max_health
The maximum health an entity can have. Usually players can have 100 health max. Now you can change that. You could use this to make different player-classes ("heavy" 200 health, "scout" 80 health).

message
Is the text that the game_text will put on your screen. This is cool because you can merge different sentence parts together. For example: "bob found a secret room."

How do you use keyvalues?
There are a couple of new entities that let you work with keyvalues. The most important are: trigger_changevalue (http://zyl.pestermom.com/external/entguide/entities/trigger_changevalue.html), trigger_copyvalue (http://zyl.pestermom.com/external/entguide/entities/trigger_copyvalue.html)and trigger_condition (http://zyl.pestermom.com/external/entguide/entities/trigger_condition.html).

The entity-guide explains very well how these entities work. But to understand them better, here is a crapload of examples on how to use them:

trigger_changevalue
Name: namechanger1
Destination Entity: door1
Destination Keyvalue: targetname
Source value: door2
Operation: Replace (= source)
Triggering this will change the name of door1 to door2.

trigger_changevalue
Name: yournameisbobnow
Destination Entity: !activator
Destination Keyvalue: netname
Source value: bob
Operation: Replace (= source)
Triggering this entity will change your name to bob! Not your entity name but your playername! The one that shows up when you press tab.

trigger_changevalue
Name: moredeath
Destination Entity: hurt1
Destination Keyvalue: dmg
Source value: 10
Operation: Add (= old + source)
Triggering this entity will increase the damage of a trigger_hurt named hurt1 by 10.

trigger_changevalue
Name: plus1apple
Destination Entity: !activator
Destination Keyvalue: $i_numberofapples
Source value: 1
Operation: Add (= old + source)
If you, the player, trigger this entity then your $i_numberofapples will increase by 1. $i_numberofapples is a custom-keyvalue and I will explain later how those work.

trigger_copyvalue
Name: teleportexplo
Source entity: zombie1
Source key: origin
Destination entity: explo1
Destination key: origin
Operation: Replace (= source)
Triggering this will copy the origin-value from zombie1 to explo1, which is an env_explosion. Do you like explosive zombies?

trigger_copyvalue
Name: applesarehealthy
Source entity: !activator
Source key: $i_numberofapples
Destination entity: !activator
Destination key: health
Operation: Add (= old + source)
Triggering this entity will give a player a healthpoint for every apple he collected earlier. $i_numberofapples is a custom-keyvalue and I will explain later how those work.

Here is an example with two entities working together

trigger_copyvalue
Name: whatsmyname
Source entity: !activator
Source key: netname
Destination entity: text1
Destination key: message
Operation: Replace (= source)
Trigger after operation: addmoretext

trigger_changevalue
Name: addmoretext
Destination Entity: text1
Destination Keyvalue: message
Source value: is super cool
Operation: Append (String concatenation)
The last two entities work together. The first one will copy the name of the player to a game_text. For example "bob". The second one will add " is super cool" to the game_text. If you trigger your game_text now it will say "bob is super cool".

trigger_condition
Name: namecheck
Monitored entity: !activator
Monitored key: netname
Compare-entity:
Compare-key:
Compare-value (alternative): bob
Comparator: == (equal)
Target for ´true´-case: door1
Target for ´false´-case: goawaytext
Constant mode trigger behaviour: Fire true/false alternatingly
Check-interval (seconds): 0.1
Flags: Cyclic;no toggle [x]
Keep !activator [x]
Triggering this will open door1. But only if your name is bob. If it is not it will trigger goawaytext which is a game_text saying: "Go away! I don´t know you!".

trigger_condition
Name: jumpchecker
Monitored entity: !activator
Monitored key: button
Compare-entity:
Compare-key:
Compare-value (alternative): 2
Comparator: == (equal)
Target for ´true´-case: funnyjumpsound1
Target for ´false´-case:
Constant mode trigger behaviour: Fire true/false alternatingly
Check-interval (seconds): 1
Flags: Start off [x]
Keep !activator [x]
If you trigger this entity then it will check every second whether you are pressing the jump key. If you do then it will trigger funnyjumpsound1.

trigger_condition
Name: barneypanic
Monitored entity: alien1
Monitored key: health
Compare-entity: barney1
Compare-key: health
Compare-value (alternative):
Comparator: > (Greater)
Target for ´true´-case: barneypanicseq
Target for ´false´-case:
Constant mode trigger behaviour: Fire true/false alternatingly
Check-interval (seconds): 0.1
Flags: Cyclic;no toggle [x]
When you trigger this entity it will check whether alien1 has more health than barney1. And if it has then it will trigger barneypanicseq. barneypanicseq is a scripted_secuence that makes the barney run away in terror because that alien has more health than he has.

Custom keyvalues (http://zyl.pestermom.com/external/entguide/generic/custom_keyvalues.html)
Now you have a basic idea how to work with the keyvalues of entities. Custom keyvalues are keyvalues that you can create as you like. Their only purpose is to store information. For example $i_numberofapples is a custom keyvalue that can be stored on any entity. In my example I stored this on player entities. So now every player has his own $i_numberofapples and this could indicate how many apples he picked up. But I could also use it to save how many times that player pressed a button, or jumped, or died. Just as I like. Here is an example:

trigger_changevalue
Name: game_playerspawn
Destination Entity: !activator
Destination Keyvalue: $i_numberofapples
Source value: 0
Operation: Replace (= source)

This entity will be triggered everytime a player respawns and make sure his $i_numberofapples is set to zero. So every player starts with 0 apples.

Keyvalues are awesome! Use your imagination!
All the examples in this tutorial are just baby-stuff. You can make really cool stuff when you combine several of these entities. wolf-3D made a tutorial on how to create a Jetpack with keyvalues (http://forums.svencoop.com/showthread.php/40391-TA-s-JetPack-Tutorial-%28bsp-Map%29). Nih explained how to make player classes (http://forums.svencoop.com/showthread.php/39092-Advanced-player-classes). In my maps I made a complete player inventory with several collectable items.
Use your imagination: You could make a money system where players can earn money and use it to buy or trade stuff. You could make an ingame keyboard where you can actually write stuff. Also PVP gameplay is possible. I will write another tutorial about that sometime.

RNG
03-12-2013, 02:52 PM
finally a tutorial about custom keyvalues that isnt gibberish (http://zyl.pestermom.com/external/entguide/generic/custom_keyvalues.html)

w00tguy123
03-12-2013, 04:54 PM
Wow this is a long overdue tutorial. Thanks for taking the time to do this.

Some more interesting keyvalues:

movetype
Defines how entities move around. This one can be a lot of fun. I've made func_pushables bounce across a room with this (see the entity guide for possible movetype values).

effects
Can turn any point entity into a dynamic light (only 2 brightness settings though).

takedamage
Use this give players/monsters god mode.

flags
Can be used to freeze players (FL_FROZEN), give them notarget (FL_NOTARGET), or check useful information (is the entity in water, on the ground, etc.).

armorvalue
player's armor value.

sequence
Which animation sequence the player/monster is using.

view_ofs
Use this to set the player's view position (e.g. lowered view height in the Zelda maps).

nextthink
When an enemy will perform it's next 'think' action (attacking players, moving around, etc.). I've used this to stall enemy AI while I performed some sequence.

RNG
09-01-2014, 10:03 AM
mind sharing tutorial of the kind of life system that is used in robination, lmsbath and tiles for example. where every player has one life and when everyone has died on the field restart and stuff is activated

i sort of painstakingly learned the "lifepool" system (thanks stream for teaching me bout that) but cant figure this one out at all

the-middleman
09-01-2014, 10:14 AM
I am currently writing a tutorial about that. I hope I can post it in the next few days.

RNG
09-01-2014, 01:41 PM
you could always pm me how to do it in some simple way

Maiten
09-01-2014, 08:13 PM
mind sharing tutorial of the kind of life system that is used in robination, lmsbath and tiles for example. where every player has one life and when everyone has died on the field restart and stuff is activated

i sort of painstakingly learned the "lifepool" system (thanks stream for teaching me bout that) but cant figure this one out at all

in tiles i have done that system with 2 trigger multiple some relay and changetarget,but sometimes it get buggy so i am going to explain a new version which works better


put 2 trigger multiple,one on the whole field,arena,combat area,whatever and other on the whole wait room,where players respawn when they die.Add one info target with one customkeyvalue,for example $i_life_system,add 2 changevalue

trigger_changevalue
Name: set_false
Destination Entity: name of info target
Destination Keyvalue: $i_life_system
Source value: 0
Operation: replace

trigger_changevalue
Name: set_true
Destination Entity: name of info target
Destination Keyvalue: $i_life_system
Source value: 1
Operation: replace

add one trigger condition

trigger_condition
Name: check_life
Monitored entity: name of info target
Monitored key: $i_life_system
Compare-value (alternative): 0
Comparator: == (equal)
Target for ´true´-case: name of your multi manager with the events when everybody dies
Target for ´false´-case:
Flags: Start off [x]
Cyclic [x]


add multimanager

multi_manager
name:start_check
set_false 0
check_life 5

configure the trigger multiple

arena trigger multiple
target:set_true
delay:1 or less

wait room trigger multple
target:start_check
delay:5.1


well when someone enter to the wait room the custom keyvalue have a value of 0,and after 5 seconds if the values stay in "0" everybody is dead,because if still are players on the field the keyvalue will be changed to 1 every second.You also have to setup multimanagers for turn off/on your spawnpoints and turn off/on the condition when the field restart/start

i am using this system on other map and never got any issue with this,cant say the same with the previous system what i have done for tiles

hope it is clear




also you made a nice tutorial "the-middleman"

Streamfox
10-01-2014, 07:31 AM
Ah yeah I had fun with custom keyvalues, made few fancy puzzles.
Also made some door which opens when players go near by it, and closes if they leave it.


@Maiten: Maybe tiles could use that updated system too.

RNG
10-01-2014, 12:41 PM
ohh thanks alot, the thing works flawlessly

Maiten
10-01-2014, 01:31 PM
ohh thanks alot, the thing works flawlessly

sorry but i made a mistake,cyclic flag shold be checked on the trigger condition


@Streamfox:yeah i am going to rewrite all the round setup of tiles

RNG
10-01-2014, 02:20 PM
oh right, the delay on it felt little odd for sure

the-middleman
20-02-2014, 05:20 PM
flags
Can be used to freeze players (FL_FROZEN), give them notarget (FL_NOTARGET), or check useful information (is the entity in water, on the ground, etc.).


Hey I am trying to make players notarget. How exactly do I do this? I tried adding 128 to flags. That kind of works. But the player is broken after that. Many entities dont recognise him as a player anymore. Have you tried this before?

w00tguy123
20-02-2014, 07:31 PM
^ I've only used that flag as a test to see if enemies would ignore me. That much works, but I haven't used it for anything else.

wolf-3d
20-02-2014, 10:58 PM
Hey I am trying to make players notarget. How exactly do I do this? I tried adding 128 to flags. That kind of works. But the player is broken after that. Many entities dont recognise him as a player anymore. Have you tried this before?

It is NOT recommended you do this with "FLAGS" for at least two reasons I can think off (and there are probably more).

1) If by accident you bitwise 128, more than once you can place "Player" is an unknown engine state. i.e. ~+256 = FL_SKIPLOCALHOST (Don't tell clients about this entity; they're predicting this entity by themselves.)

2) Even if you do change it once and only once, you still end up putting "Player" in conflict with the LINK: Like/Hate Table (classify) (http://www.svencoop.com/manual/classes.html), because other important internal engine values need to be changed at the same time.

The Recommended way of making Players "notarget" is to change "player" to same class as monster.
If you have mixed monster classes "e.g. Xen/Monsters and Enemy Soldiers/NPC's" in map, you could try setting Player to Classify "NONE".
Try - because "NONE" was buggy at some point and I can't remember if was fixed or not :(

In General it is safe to read/test "Flags" but not recommended to write to them.

the-middleman
21-02-2014, 02:37 AM
Hmm so changing flags is not really a thing in sc mapping? classify is not a good alternative because I want only some of the players to be notarget. And if I put players in different classes, they can shoot each other.

wolf-3d
21-02-2014, 10:17 AM
Players will be able to shoot each other but I think the default is they don't do Armour Strip or Armour damage (Please check this), but regardless I am almost 100% sure (been a long time since I did it) that they cannot shoot each other and cause Health Loss. (You have to put Player in different "teams" as well as different "classify" for that to happen.)

Are you trying to get some Players ignored by NPC's at the Same as time Other Players but visible? or make certain player invisible (no render) plus remove NPCs AI interaction, and Other Player HP, Armour strip ability?
( Not sure exactly what you want to happen. )

EDIT: There is also a possibility that some form of "Team" Entity will be introduced in the future (SC 5.0 or one of the steam updates after SC 5.0 comes out). This is one of the reasons I have'nt played about with these settings for a long time. But you could/can do this in SC 4.6 to SC 4.8. [Although the entity setup was a bit confusing/painful to implement.]

Hezus
25-02-2014, 04:24 PM
I couldn't get my custom keyvalue to work for the longest time and then finally figured out what was wrong. I'll just drop this here in case someone else bumps into the same problem:

Be careful in naming your custom keyvalues. Here is how to name them:

"$i_" makes the custom keyvalue an integer. (-2147483648 to 2147483647)
"$f_" makes the custom keyvalue a float.
"$v_" makes the custom keyvalue a 3D-vector, consisting of 3 floats.
"$s_" makes the custom keyvalue a string.
(without quotation marks)

As you can see it uses an underscore (_) in its prefix. Somehow the code recognizes the underscore as the end of the prefix. If you use any more underscores the code will not be able to figure out the keyvalue properly. So don't name your keyvalue $i_amount_of_monsters but $i_amountofmonsters.

I'm used to using underscores to keep my targetnames legible but apparently this messes up the custom keyvalues.

Nih
25-02-2014, 04:35 PM
Good catch Hezus. This should be added to the feature thread where custom keyvalues are mentioned.

wolf-3d
25-02-2014, 09:38 PM
Good catch Hezus. This should be added to the feature thread where custom keyvalues are mentioned.

^ in addition should sticky "Silencers website" in the "Mapping Resources" Thread.
Index (http://zyl.pestermom.com/external/entguide/)
custom_keyvalues (http://zyl.pestermom.com/external/entguide/generic/custom_keyvalues.html)

Hezus
26-02-2014, 03:11 PM
Another oddity:

You can store integers into multi_managers but they can't initially be greater than 0.

For instance:
multi_manager:
targetname: counter
$i_monsters: 5

trigger_changevalue
destination ent: counter
keyvalue: Si_monsters
source value: 1
action: subtract

If you run this sequence and let the result be displayed by a game_text, you'll find it'll give you -1 instead of the expected 4. My guess is that, once a >0 integer is initially set, the multi_manager treats it with it's usual behavior: delay time until trigger. This might also apply to other relay triggers with delays (tigger_relay, trigger_random, etc). Although I haven't tested those.

To be on the safe side, store (and calculate) within very featureless entities such as info_target.

Silencer
26-02-2014, 03:49 PM
Somehow the code recognizes the underscore as the end of the prefix. If you use any more underscores the code will not be able to figure out the keyvalue properly.

I am pretty confident I had been using undescores without problems a lot. Maybe this problem was introduced after I finished working on custom keyvalues?

And yes multi_managers are their own cup of tea. They are a hack to avoid many trigger_relays in the first place. Trigger_createentity might bitch about it as well since it also has very unique keyvalue parsing logic.

wolf-3d
27-02-2014, 06:26 AM
I am pretty confident I had been using undescores without problems a lot.

Would guess, unfortunate naming conventions + parser is while looping on length of chr$ string array (instead of doing a for(int x=1; x<=3;x++) so :
$i_amount_of_monsters becomes $f_monsters

---------------------------------------------------

EDIT: My Bad / Assumption wrong. Your switch code will not allow such and error to occur due the the need for the leading Identifier.

Silencer
27-02-2014, 08:52 AM
I don't remember writing any loops for this.

// Returns a type depending on type specifier "$i_", "$f_", "$v_" or "$s_" or VAR_INVALID if none match.
entvartype_s CCustomKeyvalues::InterpretSpecifier(const char* const key) {
entvartype_s type = VAR_INVALID;
if (key[0] == CKV_IDENTIFIER) { // Leading CKV_IDENTIFIER is required.
switch (key[1]) { // Figure out the type.
case 'i': type = VAR_INTEGER; break;
case 'f': type = VAR_FLOAT; break;
case 'v': type = VAR_VECTOR; break;
case 's': type = VAR_STRING; break;
default: return type;
}
return key[2] == '_' ? type : VAR_INVALID; // The underscore is required.
}
return type;
}

Anyway, we'll just have to debug it.

Nih
03-08-2014, 01:40 PM
Wow this is a long overdue tutorial. Thanks for taking the time to do this.

Some more interesting keyvalues:

movetype
Defines how entities move around. This one can be a lot of fun. I've made func_pushables bounce across a room with this (see the entity guide for possible movetype values).

effects
Can turn any point entity into a dynamic light (only 2 brightness settings though).

takedamage
Use this give players/monsters god mode.

flags
Can be used to freeze players (FL_FROZEN), give them notarget (FL_NOTARGET), or check useful information (is the entity in water, on the ground, etc.).

armorvalue
player's armor value.

sequence
Which animation sequence the player/monster is using.

view_ofs
Use this to set the player's view position (e.g. lowered view height in the Zelda maps).

nextthink
When an enemy will perform it's next 'think' action (attacking players, moving around, etc.). I've used this to stall enemy AI while I performed some sequence.

Movetype: Can you share the results of any testing with movetypes you've done, so mappers don't have to test it all themselves?

Nextthink: So this sets the amount of seconds before the npc thinks again?

Armorvalue: Max armor or current armor?

w00tguy123
03-08-2014, 02:46 PM
Movetype: Can you share the results of any testing with movetypes you've done, so mappers don't have to test it all themselves?
From what I tested, the movetype values only had useful effects for pushables, monsters, and players.

MOVETYPE_FLY has helped me keep monsters in the air without having to constantly set their origin.
MOVETYPE_NOCLIP can be used to give a player noclip without cheats.
Most movetypes work well with func_pushable. If you use MOVETYPE_BOUNCE it will bounce forever once you push it off a ledge. Combine this with no gravity for good times.

I don't remember anything else interesting I've done with movetypes, but the descriptions in the entity guide (http://zyl.pestermom.com/external/entguide/generic/entity_keyvalues.html) should help you pick the right one.


Nextthink: So this sets the amount of seconds before the npc thinks again?
Almost. This value stores a time relative to the server start time. So if you wanted to delay the think action you would set nextthink to the current server time plus the number of seconds you want to delay it.

I don't know of any way to get the server time directly, so I've been using a trigger_auto to start a loop that increments an integer keyvalue each second once the server starts. I haven't had any timing issues with that method (I assume triggers are linked to server time).

I've only tried this with assassins and one of the side effects was that they would loop their current animation until the nextthink time was reached (sometimes running in place).


Armorvalue: Max armor or current armor?
current armor

the-middleman
04-08-2014, 05:57 AM
About nextthink: You can simply add to the monsters current nextthink value to stall them. However this does sometimes look silly because they loop their current action (including the sounds and sprites that come with certain animations). Also it cause some weird behaviour, like monsters lagging around, for me.

the-middleman
07-09-2014, 01:12 PM
So I tried to change to bone controllers of a model with the controller-key. But that does not appear to do anything. Has anyone tried this before?

w00tguy123
07-09-2014, 06:43 PM
Yes, tried and failed. There seems to be a lot of keys that just don't do anything, or can't be written/read.

wolf-3d
08-09-2014, 01:41 PM
I have not tried or tested "PEV bone controllers" but make sure your model is Monster_generic/ or _furniture because otherwise you will be fighting the engines Default AI and bone controller code.
[i.e. Your changes will be only last a split second before being overwritten and stalling next think, will not help in this case."]

Possibly one of the coders can help as there may be default bone controller code & AI for monster_generic and monster_furniture too.