Trying to figure out a combat system
Fiskie
30 May 2014, 17:15I'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.
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
31 May 2014, 00:32There 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:
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:
but then it checks for player death with:
which won't work because "this" refers to the monster, not the player. If you change that to:
It should at least work to properly kill the player. I can't vouch for any of the other code.
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
31 May 2014, 01:53Okay, 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!
*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
31 May 2014, 02:39this 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)
---------
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.
--------
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>
(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
31 May 2014, 08:37Fiskie, there's another bug in the combat lib to be fixed.
In "makedead", change this line:
to this:
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.
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
01 Jun 2014, 18:55Well 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.
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
02 Jun 2014, 00:091. 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"><
<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"><