Turn-Based Combat?

japangirl
How can I create turn-based combat for my text adventure?

The Pixie
It is not straight-forward!

The easiest way is to use a library:
viewtopic.php?f=18&t=4886

Even that will take you some effort, as you will have to work out how to use the library, but you can set up monsters and weapons from a tab.

I am hoping to release a dungeon crawl using that library (slightly modified) in the next couple of weeks. I was planning on making the code available; that would include hundred of monsters, dozens of weapons and spells. If you do not care about the game system particularly, I could PM you a link to an early version and you can see what you think (the main issue at this stage is game balance; ensuring the player has a chance at survival).


The alternative is to do it from scratch. If you really want to reinvent the wheel, look at this "How to" page, and go down to the "Advanced" section:
http://docs.textadventures.co.uk/quest/guides/

... and read these five guides:

Use Types
Use Types and Tabs
More on Tabs (implementing a magic system)
Simple Combat System
Second Inventory Pane (listing spells for your magic system)

I wrote them whilst developing the libary I linked to above.

The other side of the issue is working out how the game will work. Imagine you are playing it on paper and rolling dice, what are the rules?

What are the effects of armour or a shield?
How do you handle ranged attacks (can you shoot an arrow from an adjacent room perhaps; does an attacker get a bonus if you are holding a bow)?
Parrying?
Positioning (flanking, back-attack, higher ground)?
What is the difference between attacking with a dagger or a polearm or a flail?
Do you track injuries by location or just total hits; what about healing?
How can magic affect combat; bonus to attack, to armour, to defence, etc.?
Does casting magic use power points, use up the spell or what?
What about magic items?
What statistics define the player, and how are they meaningful in play (why would a player want to have a good charisma)?

You really need to have these clear in your mind before you even start coding (using a library is that all this has already been decided for you, which is both good and bad).

HegemonKhan
you can also take a look at this code of mine (based upon Pertex' code design~structure), as it implements turn based combat:

(scroll down to ~ the bottom half of this post, to see the relevant code parts for how I do the entire combat sequencing)

(here's the resource I used for my own combat code, Pertex' Combat Code: viewtopic.php?f=18&t=2660 )

viewtopic.php?f=10&t=3348&start=120#p22483

<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>


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

and its key-legend (for all the stupid abrevs I used) here:

viewtopic.php?f=10&t=3348&start=120#p22486

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


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

be warned:

this is extremely old code, it is very poor and bad code, along with all of my annoying abbrevs (and I messed~mixed up some of the damage vs resistance abrevs too). I'm just too lazy to re-write a new much imporoved combat code, at least for the distant future, laughs.

that said however, please ask if you got any questions, need help, and~or don't understand whatever about it, I'll be happy to help (though it's been so long since I've worked with combat... it might take me a bit to re-fresh myself on it, lol)

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

you can have a more simple-static rounds of combat, for example:

you always go first, and then the monster~enemy~foe goes, and it repeats until the battle is ended (death, escape~fleeing~running, etc).

or, you can have more complex dynamic rounds of combat, for example:

who goes first, depends on a formula based upon at least a 'speed' stat (Attribute).

and you can make it more complex too: do you (and~or the enemy~monster~foe) get an "extra~bonus" turn ??? Or, do you or the mosnter lose a turn (you or the mosnter gets put to sleep or gets stunned, for example)

and etc complexitoes that you may have encountered within the games you've played.

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

about my code:

I use a Command, for how~when to choose to (try to) fight:

(this allows you to type in what you want to try to fight, in any room of the game, instead of clicking on the individual 'fight' Verbs buttons or the hyperlinks on every npc~character~monster)

  <command name="fight">
<pattern>fight #text#</pattern>
<script>
battle_system (game.pov,text)
</script>
</command>


I have a function for determining if you can even fight or not:

  <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>


I have a function for determining the order of who goes first and etc (battle turns and battle rounds), aka "battle sequence", seen here:

(this is extremely horribly bad code, but I'm too lazy to fix it up - despite being bad code, it does a good job of demonstrating the logic, I think)

<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>


I have a function for handling YOUR COMBAT TURN (and also then, it does the initial handling of *IF* the monster~enemy~foe turn happens or not - such as if you get an extra turn instead):

 <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)


I have a function for handling the MONSTER~ENEMY~FOE COMBAT TURN (and also then, it does the initial handling of *IF* your turn happens or not - such as if the mosnter~foe~enemy gets an extra turn instead):

 <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)

The Pixie
The Pixie wrote:...
I am hoping to release a dungeon crawl using that library (slightly modified) in the next couple of weeks. I was planning on making the code available; that would include hundred of monsters, dozens of weapons and spells. If you do not care about the game system particularly, I could PM you a link to an early version and you can see what you think (the main issue at this stage is game balance; ensuring the player has a chance at survival).
...

In fact I have now released it for beta-testing, so you can take a look at what is possible:
viewtopic.php?f=5&t=5704

japangirl
I fear that this is just too complicated for me. Is there any alternatives?

HegemonKhan
we can help you with something more simple, I was just providing my big combat code, for you to look at and see some ideas and get a feel-look for how it can be done.

we need some instructions though in order to help you, what do you want with your combat system? tell us the details of what and how you want your combat to work? what aspects or features do you want with it? What game mechanics do you want involved? etc etc etc.

---------

here's a very simple dynamic (based upon 'speed' Attribute as to who goes first, both you and the enemy get a single turn per battle round) turn-based combat, example:

(I used some redundent code, as I think it's easy for you to see it all in one place, than for me to split it up in separate places)

(when reading code, you literally read it just like a book, from top down, and hopefully you can understand it and follow along with it. ask if you want any parts of the code explained!)

<game name="xxx">
<attr name="battle_round" type="int">0</attr>
</game>

<object name="player">
<attr name="life" type="string">999/999<attr>
<attr name="current_life" type="int">999</attr>
<attr name="changedcurrent_life" type="script">
player.life = player.current_life + "/" + player.maximum_life
</attr>
<attr name="maximum_life" type="int">999</attr>
<attr name="changedmaximum_life" type="script">
player.life = player.current_life + "/" + player.maximum_life
</attr>
<attr name="damage" type="int">50</attr>
<attr name="speed" type="int">50</attr>
<attr name="statusattributes" type="simplestringdictionary">life = Life: !; damage = Damage: !; speed = Speed: !</attr>
</object>

<object name="orc">
<attr name="current_life" type="int">500</attr>
<attr name="changedcurrent_life" type="script">
orc.life = orc.current_life + "/" + orc.maximum_life
</attr>
<attr name="maximum_life" type="int">500</attr>
<attr name="damage" type="int">25</attr>
<attr name="speed" type="int">50</attr>
<attr name="dead" type="boolean">false</attr>
<attr name="displayverbs" type="simplestringlist">fight</attr>
<attr name="fight" type="script">
if (not orc.dead) {
game.battle_round = game.battle_round + 1
msg ("Your Life: " + player.life)
msg ("Orc's Life: " + orc.life)
msg ("Battle Round: " + game.battle_round)
if (player.speed > orc.speed) {
orc.current_life = orc.current_life - player.damage
msg ("You attack and damage the orc for " + player.damage + ", leaving the orc with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks, damaging you for " + orc.damage + ", leaving you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
do (orc, "fight")
}
}
} else if (player.speed < orc.speed) {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks and damages you for " + orc.damage + ", leaving the you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
orc.current_life = orc.current_life - player.damage
msg ("You attack the orc, damaging it for " + player.damage + ", leaving it with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
do (orc, "fight")
}
}
} else {
if (RandomChance (50)) {
orc.current_life = orc.current_life - player.damage
msg ("You attack and damage the orc for " + player.damage + ", leaving the orc with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks, damaging you for " + orc.damage + ", leaving you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
do (orc, "fight")
}
}
} else {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks and damages you for " + orc.damage + ", leaving the you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
orc.current_life = orc.current_life - player.damage
msg ("You attack the orc, damaging it for " + player.damage + ", leaving it with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
do (orc, "fight")
}
}
}
}
} else {
msg ("The orc is already dead, silly.")
}
</attr>
</object>

<verb>
<property>fight</property>
<pattern>fight</pattern>
<defaultexpression>You can't fight that!</defaultexpression>
</verb>


My apologies if the code scares you, but it'd take so much longer to do all of this for you through instructions via using the GUI~Editor's Scripts (add new scripts), unfortunately.

we can help you do all of this through the GUI~Editor, just ask for help.

japangirl
HegemonKhan wrote:we can help you with something more simple, I was just providing my big combat code, for you to look at and see some ideas and get a feel-look for how it can be done.

we need some instructions though in order to help you, what do you want with your combat system? tell us the details of what and how you want your combat to work? what aspects or features do you want with it? What game mechanics do you want involved? etc etc etc.

---------

here's a very simple dynamic (based upon 'speed' Attribute as to who goes first, both you and the enemy get a single turn per battle round) turn-based combat, example:

(I used some redundent code, as I think it's easy for you to see it all in one place, than for me to split it up in separate places)

(when reading code, you literally read it just like a book, from top down, and hopefully you can understand it and follow along with it. ask if you want any parts of the code explained!)

<game name="xxx">
<attr name="battle_round" type="int">0</attr>
</game>

<object name="player">
<attr name="life" type="string">999/999<attr>
<attr name="current_life" type="int">999</attr>
<attr name="changedcurrent_life" type="script">
player.life = player.current_life + "/" + player.maximum_life
</attr>
<attr name="maximum_life" type="int">999</attr>
<attr name="changedmaximum_life" type="script">
player.life = player.current_life + "/" + player.maximum_life
</attr>
<attr name="damage" type="int">50</attr>
<attr name="speed" type="int">50</attr>
<attr name="statusattributes" type="simplestringdictionary">life = Life: !; damage = Damage: !; speed = Speed: !</attr>
</object>

<object name="orc">
<attr name="current_life" type="int">500</attr>
<attr name="changedcurrent_life" type="script">
orc.life = orc.current_life + "/" + orc.maximum_life
</attr>
<attr name="maximum_life" type="int">500</attr>
<attr name="damage" type="int">25</attr>
<attr name="speed" type="int">50</attr>
<attr name="dead" type="boolean">false</attr>
<attr name="displayverbs" type="simplestringlist">fight</attr>
<attr name="fight" type="script">
if (not orc.dead) {
game.battle_round = game.battle_round + 1
msg ("Your Life: " + player.life)
msg ("Orc's Life: " + orc.life)
msg ("Battle Round: " + game.battle_round)
if (player.speed > orc.speed) {
orc.current_life = orc.current_life - player.damage
msg ("You attack and damage the orc for " + player.damage + ", leaving the orc with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks, damaging you for " + orc.damage + ", leaving you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
do (orc, "fight")
}
}
} else if (player.speed < orc.speed) {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks and damages you for " + orc.damage + ", leaving the you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
orc.current_life = orc.current_life - player.damage
msg ("You attack the orc, damaging it for " + player.damage + ", leaving it with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
do (orc, "fight")
}
}
} else {
if (RandomChance (50)) {
orc.current_life = orc.current_life - player.damage
msg ("You attack and damage the orc for " + player.damage + ", leaving the orc with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks, damaging you for " + orc.damage + ", leaving you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
do (orc, "fight")
}
}
} else {
player.current_life = player.current_life - orc.damage
msg ("The orc attacks and damages you for " + orc.damage + ", leaving the you with only " + player.current_life + " life left.")
if (player.current_life <= 0) {
msg ("You were killed by the orc.")
msg ("GAME OVER")
finish
} else {
orc.current_life = orc.current_life - player.damage
msg ("You attack the orc, damaging it for " + player.damage + ", leaving it with only " + orc.current_life + " life left.")
if (orc.current_life <= 0) {
orc.dead = true
msg ("You killed the orc!")
game.battle_round = 0
} else {
do (orc, "fight")
}
}
}
}
} else {
msg ("The orc is already dead, silly.")
}
</attr>
</object>

<verb>
<property>fight</property>
<pattern>fight</pattern>
<defaultexpression>You can't fight that!</defaultexpression>
</verb>


My apologies if the code scares you, but it'd take so much longer to do all of this for you through instructions via using the GUI~Editor's Scripts (add new scripts), unfortunately.

we can help you do all of this through the GUI~Editor, just ask for help.

I'm looking for something which displays Images, weapon stats that affect the Player Stats as well as the opponent/opponents that you're facing off against. Armour Points, health, regenerating health, speed, dodging ability, and a lot more stuff similar to that.

HegemonKhan
unfortunately, that's a lot of very advanced and complex stuff, it's going to take quite some time to teach it to you (we can create something for you to use, of course, but it's better if you can learn how to do it, as that way you can use that knowledge for many other things that you'll want to do).

This will take us some time, (longer for me who's not as good at coding or worse it's beyond my ability lol, whereas the others who are good at coding, can get this created faster and better for you), as you want help with developing an entire combat system. We'll need more details as well, how do you want us to implement those stats and features (like regenerating health), and etc etc etc.

---------

all that said,

you'd be better off, learning how to use Pixie's Combat Code~Library, as he~she has some of this stuff already done for us.

XanMag
Never contract 'who' and 'are', HK! :lol:

HegemonKhan
where did I do that? laughs... I'll change it... never even realized... the contraction comes to that... oops!

HK edit: found at least one of them... do I have more?

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

Support

Forums