Trying to figure out a combat system

Fiskie
I've been messing with Quest (I downloaded the windows desktop version) for a few days now, and I decided to add the Simple Combat System
http://quest5.net/wiki/Simple_Combat_System_(Advanced)
to my game. I think I added everything to my code, added the combat library, I can equip and unequip weapons, and I made a monster that should kill me in one hit. he manages to deal a couple thousand damage when he hits me, but that just leaves me with negative hp, and the game never ends.

I need someone who can help me figure out what I did wrong with adding this code,
or,
someone who can suggest a better combat system. I like this combat system and what it seems to be able to do, but I'm sure there are probably better ones out there.

I noticed this one doesn't use the default health system, and therefore the "health" indicator in the GUI doesn't work. is there any way to put your HP on the GUI?


I attached the game as an attachment. please note that this game is not fun at all, and I know that. I was merely trying to learn the mechanics of quest. In fact, the idea of this game was to be as bland and generic as possible, so I could focus on learning how to do things with the quest engine. Any tips about the way I did something technical are appreciated, but otherwise understand that this game is very bland and has been done a million times before. This is by design.

In order to get out of the first room, follow the hyperlinks, or the walkthrough to
Take the lockpick out of the corpse's pocket
pick the lock

The corpse's arm is a weapon that adds a 9999 damage bonus. this is clearly a placeholder, to test monster death.

the orc is in the room to the west. he has a hp of 9999 and deals 2000 or so damage per hit. these are of course placeholder values, with which to test the combat system.

jaynabonne
There seem to be a couple of bugs in the combat library.

First, the library assumes that the monster has an alias set, which is why you're getting output like:

"swings at you and hits, doing 2456 points of damage." If instead of "this.alias", the code had used:

GetDisplayAlias(this)

then it would have worked regardless, in both cases. To work around that, if you give the Orc an alias "Orc", then it will display properly.

The problem you're asking about is a bug in the "attackplayer" script. It properly decrements the player's health with:

game.pov.hitpoints = game.pov.hitpoints - damage

but then it checks for player death with:

if (this.hitpoints <= 0) {
msg ("You are dead!")
finish
}

which won't work because "this" refers to the monster, not the player. If you change that to:

if (game.pov.hitpoints <= 0) {
msg ("You are dead!")
finish
}

It should at least work to properly kill the player. I can't vouch for any of the other code. :)

Fiskie
Okay, now I die, and the aliases work, but there doesn't seem to be a message when the orc dies (it does die properly, it just says nothing). do I need to reupload my game files now that they've changed slightly?

*edit: I see there's a description on death field, let me fill that in and see if it works.

*edit 2: something very odd just happened.

> fight orc
You swing your fists and hit, doing 7 points of damage; The orc falls to the ground, dead.
Error running script: Error compiling expression 'monster': Unknown object or variable 'monster'
Orc (dead) swings at you and hits, doing 7 points of damage.

> fight orc
You swing your fists and miss.
Orc (dead) swings at you and hits, doing 8 points of damage.
You are dead!

*edit 3: this happens every time I kill the orc.

*edit 4: he's not only dead, he's dead dead dead.

> hit orc
You swing your Corpse Arm and miss.
Orc swings at you and hits, doing 7 points of damage.

> hit orc
You swing your Corpse Arm and hit, doing 10008 points of damage; The orc falls to the ground, causing the ground to shake.
Error running script: Error compiling expression 'monster': Unknown object or variable 'monster'
Orc (dead) swings at you and hits, doing 8 points of damage.

> hit orc
You swing your Corpse Arm and miss.
Orc (dead) swings at you and misses.

> hit orc
You swing your Corpse Arm and miss.
Orc (dead) swings at you and hits, doing 6 points of damage.

> hit orc
You swing your Corpse Arm and hit, doing 10003 points of damage; The orc falls to the ground, causing the ground to shake.
Error running script: Error compiling expression 'monster': Unknown object or variable 'monster'
Orc (dead) (dead) swings at you and misses.

> hit orc
You swing your Corpse Arm and miss.
Orc (dead) (dead) swings at you and hits, doing 3 points of damage.

> hit orc
You swing your Corpse Arm and hit, doing 10010 points of damage; The orc falls to the ground, causing the ground to shake.
Error running script: Error compiling expression 'monster': Unknown object or variable 'monster'
Orc (dead) (dead) (dead) swings at you and hits, doing 4 points of damage.
You are dead!

HegemonKhan
this is quite a bit more advanced combat system (and it uses a different structure: turn based: stuck in giant combat script blocks), but hopefully at least you might get some ideas and maybe understand a bit of it too (though it is in code, and it's quest version 530, whereas, you're probably using quest version 550, so you probably won't be able to get it to work, unless someone wants to convert its scripts over to the new version's syntax~format):

(and it's old code, along with my annoying abrevs which I've learned since to never do again lol, and I am too lazy to try to find my better code)

<asl version="530">
<include ref="English.aslx" />
<include ref="Core.aslx" />
<game name="Testing Game Stuff">
<gameid>d83ba5bb-2e3c-4f31-80c9-3e88a2dc082c</gameid>
<version>1.0</version>
<pov type="object">player</pov>
<start type="script">
cc
</start>
<turns type="int">0</turns>
<statusattributes type="stringdictionary">turns = </statusattributes>
</game>
<object name="room">
<inherit name="editor_room" />
<object name="player">
<inherit name="defaultplayer" />
<inherit name="pc" />
<cur_hp type="int">999</cur_hp>
<max_hp type="int">999</max_hp>
<str type="int">100</str>
<end type="int">100</end>
<dex type="int">100</dex>
<agi type="int">100</agi>
<spd type="int">100</spd>
<hc type="int">100</hc>
<pd type="int">100</pd>
<pr type="int">100</pr>
</object>
<object name="orc1">
<inherit name="editor_object" />
<inherit name="npc" />
<hostile type="boolean">true</hostile>
<dead type="boolean">false</dead>
<alias>orc</alias>
<cur_hp type="int">999</cur_hp>
<max_hp type="int">999</max_hp>
<str type="int">25</str>
<end type="int">25</end>
<dex type="int">25</dex>
<agi type="int">25</agi>
<spd type="int">25</spd>
<hc type="int">25</hc>
<pd type="int">25</pd>
<pr type="int">25</pr>
</object>
</object>
<turnscript name="game_turns">
<enabled />
<script>
sa
game.turns = game.turns + 1
</script>
</turnscript>
<command name="fight">
<pattern>fight #text#</pattern>
<script>
battle_system (game.pov,text)
</script>
</command>
<type name="char">
<cur_hp type="int">0</cur_hp>
<drop type="boolean">false</drop>
<defending type="boolean">false</defending>
<max_hp type="int">0</max_hp>
<str type="int">0</str>
<end type="int">0</end>
<dex type="int">0</dex>
<agi type="int">0</agi>
<spd type="int">0</spd>
<hp type="int">0</hp>
<hc type="int">0</hc>
<pd type="int">0</pd>
<pr type="int">0</pr>
</type>
<type name="pc">
<inherit name="char" />
<statusattributes type="stringdictionary">hp = ;str = ;end = ;dex = ;agi = ;spd = ;hc = ;pd = ;pr = </statusattributes>
</type>
<type name="npc">
<inherit name="char" />
<dead type="boolean">false</dead>
<hostile type="boolean">false</hostile>
<displayverbs type="list">Look at; Talk; Fight</displayverbs>
</type>
<function name="cc">
msg ("What is your name?")
get input {
game.pov.alias = result
msg (" - " + game.pov.alias)
show menu ("What is your gender?", split ("male;female" , ";"), false) {
game.pov.gender = result
show menu ("What is your race?", split ("human;dwarf;elf" , ";"), false) {
game.pov.race = result
show menu ("What is your class?", split ("warrior;cleric;mage;thief" , ";"), false) {
game.pov.class = result
msg (game.pov.alias + " is a " + game.pov.gender + " " + game.pov.race + " " + game.pov.class + ".")
wait {
ClearScreen
}
}
}
}
}
</function>
<function name="sa">
game.pov.hp = game.pov.cur_hp + " / " + game.pov.max_hp
</function>
<function name="battle_system" parameters="self,text" type="boolean">
first_value = false
enemy = GetObject (text)
if (enemy = null) {
foreach (obj,AllObjects()) {
if (obj.alias=text) {
enemy = obj
}
}
}
if (enemy = null) {
msg ("There is no " + text + " here.")
first_value = false
}
else if (not Doesinherit (enemy,"npc")) {
msg ("You can not battle that!")
first_value = false
}
else if (not npc_reachable (enemy)) {
msg ("There is no " + enemy.alias + " in your vicinity.")
first_value = false
}
else if (GetBoolean (enemy,"dead") = true) {
msg (enemy.alias + " is already dead.")
first_value = false
}
else if (GetBoolean (enemy,"hostile") = false) {
msg (enemy.alias + " is not hostile.")
first_value = false
}
else if (battle_sequence (self,enemy) = true) {
msg ("The battle is over.")
first_value = true
}
return (first_value)
</function>
<function name="battle_sequence" parameters="self,enemy" type="boolean"><![CDATA[
second_value = false
if (enemy.dead = false) {
if (GetInt (self,"spd") > GetInt (enemy,"spd")) {
on ready {
msg ("You get to go first for this round")
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
}
on ready {
if (enemy.dead = false) {
if (enemy_battle_turn (self,enemy) = true) {
msg ("The round has ended.")
}
}
}
on ready {
battle_sequence (self,enemy)
}
}
else if (GetInt (self,"spd") < GetInt (enemy,"spd")) {
on ready {
msg (enemy.alias + " gets to go first for this round.")
if (enemy_battle_turn (self,enemy) = true) {
msg ("It is now your turn.")
}
}
on ready {
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
else {
msg ("The round has ended.")
}
}
on ready {
battle_sequence (self,enemy)
}
}
else if (GetInt (self,"spd") = GetInt (enemy,"spd")) {
if (RandomChance (50) = true) {
on ready {
msg ("You get to go first for this round")
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
}
on ready {
if (enemy_battle_turn (self,enemy) = true) {
msg ("The round has ended.")
}
}
on ready {
battle_sequence (self,enemy)
}
}
else {
on ready {
msg (enemy.alias + " gets to go first for this round.")
if (enemy_battle_turn (self,enemy) = true) {
msg ("It is now your turn.")
}
}
on ready {
if (self_battle_turn (self,enemy) = true) {
battle_sequence (self,enemy)
}
else {
msg ("The round has ended.")
}
}
on ready {
battle_sequence (self,enemy)
}
}
}
}
else {
second_value = true
}
return (second_value)
]]></function>
<function name="self_battle_turn" parameters="self,enemy" type="boolean"><![CDATA[
third_value = false
msg (self.alias + " has " + self.cur_hp + " HP left.")
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
wait {
show menu ("What is your battle choice?", split ("Attack;Defend;Cast;Item;Run", ";"), false) {
switch (result) {
case ("Attack") {
fourth_value = false
if (RandomChance (GetInt (enemy,"agi") - GetInt (self,"spd")) = true) {
msg (enemy.alias + "evaded your attack!")
fourth_value = true
}
else if (RandomChance (GetInt (enemy,"Dex") - GetInt (self,"agi")) = true) {
msg (enemy.alias + "parried your attack!")
fourth_value = true
}
else if (RandomChance (GetInt (enemy,"agi") - GetInt (self,"dex")) = true) {
msg (enemy.alias + "blocked your attack!")
fourth_value = true
}
else if (RandomChance (GetInt (self,"dex") - GetInt (enemy,"spd")) = false) {
msg ("Your attack missed " + enemy.alias +"!")
fourth_value = true
}
else if (RandomChance (GetInt (enemy,"pr") - GetInt (self,"hc")) = true) {
msg ("Your attack got resisted by " + enemy.alias +"!")
fourth_value = true
}
else if (fourth_value = false) {
if (self.defending = true and enemy.defending = true) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * 2 * GetInt (self,"pd") / 2 + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
self.defending = false
}
else if (self.defending = true and enemy.defending = false) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * 2 * GetInt (self,"pd") + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
self.defending = false
}
else if (self.defending = false and enemy.defending = true) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * GetInt (self,"pd") / 2 + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
}
else if (self.defending = false and enemy.defending = false) {
enemy.cur_hp = enemy.cur_hp - (crit_hit (self) * GetInt (self,"pd") + GetInt (self,"pd") * (GetInt (self,"str") - GetInt (enemy,"end")) / 100)
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
}
}
}
case ("Defend") {
if (self.defending = false) {
self.defending = true
}
}
case ("Cast") {
self.defending = false
}
case ("Item") {
self.defending = false
}
case ("Run") {
self.defending = false
}
}
if (GetInt (enemy,"cur_hp") > 0) {
if (RandomChance (GetInt (self,"spd") - GetInt (enemy,"spd")) = true) {
msg ("You get an extra battle turn!")
self_battle_turn (self,enemy)
}
else {
msg ("Your battle turn is over.")
third_value = false
}
}
else if (GetInt (enemy,"cur_hp") <= 0) {
msg (enemy.alias + " is dead.")
msg ("You have won the battle!")
enemy.defending = false
enemy.dead = true
third_value = true
wait {
ClearScreen
}
}
}
}
return (third_value)
]]></function>
<function name="enemy_battle_turn" parameters="self,enemy" type="boolean"><![CDATA[
fifth_value = false
msg (self.alias + " has " + self.cur_hp + " HP left.")
msg (enemy.alias + " has " + enemy.cur_hp + " HP left.")
result = GetRandomInt (1,3)
switch (result) {
case (1) {
sixth_value = false
if (RandomChance (GetInt (self,"agi") - GetInt (enemy,"spd")) = true) {
msg ("You have evaded the attack!")
sixth_value = true
}
else if (RandomChance (GetInt (self,"dex") - GetInt (enemy,"agi")) = true) {
msg ("You have parried the attack!")
sixth_value = true
}
else if (RandomChance (GetInt (self,"agi") - GetInt (enemy,"dex")) = true) {
msg ("You have blocked the attack!")
sixth_value = true
}
else if (RandomChance (GetInt (enemy,"dex") - GetInt (self,"spd")) = false) {
msg (enemy.alias +"'s attack missed!")
sixth_value = true
}
else if (RandomChance (GetInt (self,"pr") - GetInt (enemy,"hc")) = true) {
msg ("You resisted the attack!")
sixth_value = true
}
else if (sixth_value = false) {
if (enemy.defending = true and self.defending = true) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * 2 * GetInt (enemy,"pd") / 2 + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
enemy.defending = false
}
else if (enemy.defending = true and self.defending = false) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * 2 * GetInt (enemy,"pd") + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
enemy.defending = false
}
else if (enemy.defending = false and self.defending = true) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * GetInt (enemy,"pd") / 2 + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
}
else if (enemy.defending = false and self.defending = false) {
self.cur_hp = self.cur_hp - (crit_hit (enemy) * GetInt (enemy,"pd") + GetInt (enemy,"pd") * (GetInt (enemy,"str") - GetInt (self,"end")) / 100)
msg (self.alias + " has " + self.cur_hp + " HP left.")
}
}
}
case (2) {
if (enemy.defending = false) {
msg (enemy.alias + " has choosen to defend itself.")
enemy.defending = true
}
}
case (3) {
enemy.defending = false
msg ("Cast")
}
}
if (GetInt (self,"cur_hp") > 0) {
if (RandomChance (GetInt (enemy,"spd") - GetInt (self,"spd")) = true) {
msg (enemy.alias + " gets an extra battle turn!")
wait {
enemy_battle_turn (self,enemy)
}
}
else {
msg (enemy.alias + " 's battle turn is over.")
fifth_value = true
}
}
else if (GetInt (self,"cur_hp") <= 0) {
msg (self.alias + " has died.")
msg ("GAME OVER")
finish
}
return (fifth_value)
]]></function>
<function name="npc_reachable" parameters="object" type="boolean">
value = false
foreach (x,ScopeReachableNotHeld ()) {
if (x=object) {
value = true
}
}
return (value)
</function>
<function name="crit_hit" parameters="object" type="int">
if (RandomChance (GetInt (object,"luck")) = true) {
value = 2
}
else {
value = 1
}
return (value)
</function>
</asl>


01. cc = character creation function
02. sa = status attributes (mainly for implementing/displaying of ' cur / max ' stats) function
03. char = character object type ("pcs", "npcs", "monsters", etc., so, not a room, item, equipment, spell, etc)
04. pc = playable character object type ("player" characters / game.povs)
05. npc = non-playable character ("people", "monsters", and etc, so not a "player" character / not a game.pov, I'm going to have a hostility system, so any npc can be friendly or hostile, instead of having an actual "monster/enemy" type set aside)
06. hp = hit points (life) stat attribute
07. mp = mana points (magic) stat attribute
08. str = strength (physical damage, carry weight / equipment requirement, etc) stat attribute
09. end = endurance (physical defense, and etc) stat attribute
10. dex = dexterity (weapon~attack skill, think of this as "if your attack connects or not, do you 'whiff' or not", so not to gete confused with hc, and etc) stat attribute
11. agi = agility (dodging/evading, and etc) stat attribute
12. spd = speed (who goes first in battle, extra battle turns, escaping from battle, and etc) stat attribute
13. hc = hit chance (think of this more as piercing their armor or not, so not to get confused with dex, and etc) stat attribute
14. pd = physical damage stat attribute
15. fp = fire damage stat attribute
16. wp = water damage stat attribute
17. ap = air damage stat attribute
18. ed = earth damage stat attribute
19. ld = light damage stat attribute
20. dd = dark damage stat attribute
21. pr = physical resistance stat attribute
22. fr = fire resistance stat attribute
23. wr = water resistance stat attribute
24. ar = air resistance stat attribute
25. er = earth resistance stat attribute
26. lr = light resistance stat attribute
27. dr = dark resistance stat attribute
28. defending = boolean (reduces damage done for that character and increases the damage done by that character, if they chosoe to attack on the next turn)
29. escaped = boolean, run from battle (not completed/implemented yet)
30. hostile = boolean, any npc can be friendly or a(n) "monster/enemy", based upon a hostility scale (0-100), but not completed
31. dead = boolean
32. crit_hit = critical hit (bonus damage based upon luck)
33. luck = luck stat attribute
34. lvl = level stat attribute
35. exp = experience stat attribute
36. cash = cash stat attribute (currency)
37. lvlup = level up function


---------

as for your new troubleshooting issue(s), if you could post your game code (or your game file) again, we can trouble shoot it for you.

--------

Fiskie wrote:I noticed this one doesn't use the default health system, and therefore the "health" indicator in the GUI doesn't work. is there any way to put your HP on the GUI?


just find what is the Attribute Name for Pixie's Simple Combat Library's 'life stat', and then:

"game" (object) -> Attributes (tab) -> Status Attributes -> Add ->

Attribute Name (whatever it is called): (whatever Pixie's 'life stat' Attribute Name is)
Value~Field (whatever it is called): !

----

for example of a custom 'life' Attribute (using my own labeling structure, hehe):

Creating~Setting (Adding) the 'HP~Life' Attribute:

"player" (object) -> Attributes (tab) -> Attributes -> Add ->

Object: player

Attribute Name: current_hit_point_integer
Attribute Type: int (integer)
Attribute Value: 999

Attribute Name: maximum_hit_point_integer
Attribute Type: int (integer)
Attribute Value: 999

Attribute Name: hit_point_integer_string
Attribute Type: string
Attirbute Value: 999 / 999 HP

Attribute Name: changedcurrent_hit_point_integer
// 'changed______' is a special built-in script: if~when 'current_hit_point_integer' changes in value, then do the attribute value below
Attribute Type: script
Attribute Value: hit_point_integer_string = current_hit_point_integer + " / " + maximum_hit_point_integer + " HP"

Attribute Name: changedmaximum_hit_point_integer
// 'changed______' is a special built-in script: if~when 'maximum_hit_point_integer' changes in value, then do the attribute value below
Attribute Type: script
Attribute Value: hit_point_integer_string = current_hit_point_integer + " / " + maximum_hit_point_integer + " HP"

to display~show the 'HP~Life' Attribute during game play in the right pane:

(this is using a bit more complexity of displayment~showing of: 999 / 999 HP)

"player" (object) -> Attributes (tab) -> Status Attributes -> Add ->

Name (whatever it is called): hit_point_integer_string
Value (whatever it is called): 999 / 999 HP

in code~script, it's 'creation tag' looks like this:

<object name="player">
-> <inherit name="editor_object" />
-> <inherit name="editor_player" />
-> <attr name="current_hit_point_integer" type="int">999</attr>
-> <attr name="maximum_hit_point_integer" type="int">999</attr>
-> <attr name="hit_point_integer_string" type="string">999 / 999 HP</attr>
-> <attr name="changedcurrent_hit_point_integer" type="script">
->-> player.hit_point_integer_string = player.current_hit_point_integer + " / " + player.maximum_hit_point_integer + " HP"
-> </attr>
-> <attr name="changedmaximum_hit_point_integer" type="script">
->-> player.hit_point_integer_string = player.current_hit_point_integer + " / " + player.maximum_hit_point_integer + " HP"
-> </attr>
-> <attr name="statusattributes" type="simplestringdictionary">hit_point_integer_string = !</attr>
-> <attr name="damage_integer" type="int">100</attr>
</object>

<object name="orc_1">
-> <inherit name="editor_object" />
-> <alias>orc</alias>
-> <attr name="current_hit_point_integer" type="int">500</attr>
-> <attr name="maximum_hit_point_integer" type="int">500</attr>
-> <attr name="hit_point_integer_string" type="string">500 / 500 HP</attr>
-> <attr name="dead_boolean" type="boolean">false</attr>
-> <attr name="damage_integer" type="int">50</attr>
-> // Your "orc" (custom) Verb 'Fight" 's Scripting below:
-> <attr name="fight" type="script"><![CDATA[
->-> if (this.dead = true) {
->->-> msg (this.alias + " is already dead, silly.")
->-> } else if (this.dead = false) {
->->-> this.current_hit_point_integer = this.current_hit_point_integer - player.damage
->->-> msg ("You hit the " + this.alias + " for " + player.damage + " damage, the " + this.alias + " has " + this.current_hit_point_integer + " HP left.")
->->-> player.current_hit_point_integer = player.current_hit_point_integer - this.damage
->->-> msg ("The " + this.alias + " hits you for" + this.damage + " damage, you only have " + player.current_hit_point_integer + " HP left.")
->->-> if (player.current_hit_point_integer <= 0) {
->->->-> msg ("You were killed by the " + this.alias + ".")
->->->-> msg ("GAME OVER")
->->->-> finish
->->-> }
->->-> if (this.current_hit_point_integer <= 0) {
->->->-> this.dead = true
->->->-> msg ("You killed the " + this.alias)
->->-> }
->-> }
-> ]]></attr>
-> <attr name="displayverbs" type="listextend">Fight</attr>
</object>

jaynabonne
Fiskie, there's another bug in the combat lib to be fixed.

In "makedead", change this line:

monster.look = this.lookwhendead


to this:

this.look = this.lookwhendead

That's where the "Unknown object or variable 'monster'" is coming from. The routine is failing halfway through due to that, so it updates the monster's status to include "(dead)" but never gets to the part where it actually sets the "dead" flag to true. So the monster lived in.

That should fix *that* problem.

Fiskie
Well that seems to have worked, but I have a few questions.

1) is there any way to toggle a NPC's aggressiveness via a script with this setup? say a bad dialogue tree could make a person aggressive?

2) is there any way to make a dead body lootable? I tried making him a container, but I could open him before he was dead.. maybe he could just empty his inventory into the room as part of being marked dead?

3) I found the (dead) (dead) (dead) bug funny, and noticed that you can continue to beat on a dead body after it's dead. I was wondering if I could add an extra (dead) for every time it passed a threshold of negative. in other words,when it was -10 it'd be (dead) (dead), -20 would be (dead)(dead)(dead), etc.

4) Is there any way to resurrect the dead? that might be an interesting mechanic, say if it changed their name.

Necromancer resurrected Imp (dead)
Undead Imp (dead) hit you etc.

>hit imp
you hit the Undead Imp (dead), (etc) and he dies.

(imp is now named imp (dead) (dead) and can no longer perform combat actions unless resurrected again)

or the resurrection action could toggle a value (monster.resurrected ?) and via that we could make it so that resurrection could only happen once with a if statement in the resurrection action.

HegemonKhan
1. I don't know about Pixie's Simple Combat Library, but you can simply make a 'orc.hostility=0' Integer Attribute and~or also as well, a 'orc.hostile=false' Boolean Attribute, which can then thus be used via the "if" Script:

<object name="orc">
-> <inherit name="editor_object" />
-> <attr name="hostility_integer" type="int">0</attr>
-> <attr name="hostile_boolean" type="boolean">false</attr>
-> <attr name="fight_script" type="script"><![CDATA[
->-> if (this.hostility_integer > 50) {
->->-> // your fight scripts
->-> } else if (this.hostility_integer <= 50) {
->->-> msg ("You don't want to attack a non-hostile NPC, as you don't want to commit a crime, have a bounty, and be hunted down")
->-> }
-> </attr>
</object>

you can also use the boolean:

if (orc.hostile_boolean = true) {
-> // you fight scripts
} else if (orc.hostile_boolean = false) {
-> msg ("You can't attack a non-hostile npc!")
}

or, you could do both:

->-> if (this.hostility_integer > 50) {
->->-> this.hostile_boolean = true
->-> } else if (this.hostility_integer <= 50) {
->->-> this.hostile_boolean = false
->-> }
-> </attr>
</object>

if (orc.hostile_boolean = true) {
-> // you fight scripts
} else if (orc.hostile_boolean = false) {
-> msg ("You can't attack a non-hostile npc!")
}

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

2. yes, alter Attributes (such as 'cash~gold', much easier and cleaner and better than using actual Objects (unless you need to do so: equipment ~ items ~ spells).

<object name="orc">
-> <inherit name="editor_object" />
-> <attr name="dead" type="boolean">false</attr>
-> <attr name="cash" type="int">50</attr>
-> <attr name="fight" type="script"><![CDATA[
->-> if (orc.dead = true) {
->->-> if (orc.cash > 0) {
->->->-> player.cash = player.cash + orc.cash
->->->-> msg ("The orc is dead, and you loot it of its cash")
->->-> }
->->-> if (not orc.inventory = null) {
->->->-> foreach (item_x, orc.inventory) {
->->->->-> item_x.parent = player
->->->-> }
->->->-> msg ("The orc is dead, and you loot it of its items")
->->-> }
->->-> if (orc.cash <= 0 and orc.inventory = null) {
->->->-> msg ("You already looted the dead orc's body")
->->-> }
->-> } else if (orc.dead = false) {
->->-> orc.dead = true
->->-> msg ("you kill the orc.")
->-> }
-> </attr>
-> <object name="sword">
->-> // blah code~attribute lines
-> </object>
-> <object name="platemail">
->-> // blah code~attribute lines
-> </object>
</object>

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

3. um... why would you want to do that, other than 'code curiousity', lol

for your actual game, you want to prevent it from happening, once your 'orc' is dead, it should be dead, you don't attack it, and etc...

(see #2 for example)

a neat thing to do is be able to 'revive' (and de-hostile ~ 'charm') a npc~monster..

(have you ever played any of The Elder Scroll Games: Daggerfall, Arena, Morrowind, Oblivion, Skyrim ??? these games have lots of really cool code+game system designs ~ I am using these games for ideas in building my own quest RPG... maybe I'll have it done 50 years later... lol... )

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

4. lol speaking of revival... haha... this is your 4th question... we think alike, great minds think alike, hehe

yes, "revival" is quite easy:

orc.dead_boolean = false
~or~
orc.condition_string = "alive" // err, or: "undead" // or: "resurrected"

though creating a spell-magic system is a bit advanced, I'm still working on understanding it better, but if you're interested, check out Pixie's Spell Library (it's hidden in the tutorial, or here too: http://quest5.net/wiki/How_to , go to the 'using types' section of the tutorial or the 'how to' , as I think it starts there, look at the other sections too below it: 'using types and tabs', more on tabs', and etc).

also, for seeing labeled names during game play:

wooden sword (equipped)

go to this site's "code and library" board forum, and check out Chase's Wearables (equipment) Library, as you can use it's method for labeling other things too, obviously, such as your wish of, for example:

resurrected mage (lich: undead)

---------

hope this post helps you, hehe :D

This topic is now closed. Topics are closed after 60 days of inactivity.

Support

Forums