Help with an animated RPG combat system?

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Message
Author
kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

#16 Post by kamiomi »

Thanks, that worked! Using the old version in a few places, I've still been able to display just the enemy's or just the player's stats - whenever one is not on the screen (such as at the beginning or end of the battle, or if one runs away).

Before I dive into trying to create custom ui objects for the battle menu and text (which I'm sure I'll have plenty of questions about, maybe tomorrow or wednesday) - I want to post my demo version 2:


http://www.flipdrive.com/file/32cdb56a0 ... c3dedb.zip


This has multiple monster and character types (I used the same graphics in different colors, but for a real application, it would be easy to swap out unique graphics for each character), spells, healing, levels, missing attacks, and of course the stat windows.

changes to be made:
1. I think I'm going to change the "Use Potion" menu item, for a "Use Item" menu - and add "Hi-Potion", "Shield", or other one-use items.
2. Like I said, I want to change the text displays so that it's not using the game's own window and text settings (that might be as simple as just making a "battle narrator" character, putting the text under that character, and making the name black so that it won't show up on the black background).
- And all the battle menus, I want to change to a custom menu, instead of the game's default menu -- so that the rest of the game can use different menu settings (like a button menu, for example).
3. I think I'd like to add at least one more background, to test out, and demonstrate the ability to call a "battle", from different scenes.

Then it'll be more or less ready to be used in a game. The monster list, character list, spell list, and damage / hit calculations could use some tweaking and customizing, but it'll work as it is - and it can be tailored to a more specific game.

And that'll be cool.

:mrgreen:

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

#17 Post by DaFool »

That is cool. I'm very tempted to whip up something using this engine and my own graphics. Credit will be given of course! Yay for battle engine contributors (Counter Arts and yourself)

The only issue I see is that it's 1 vs 1 and most scenarios require squad-based tactics.

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

#18 Post by kamiomi »

I had been basing it on the old Shining Force games -- as I recall, there were a bunch of characters on a battle map, and you would move them into single combat (almost like a chessboard) - the actual combat would be one-on-one.

That's beyond the scope of what I want to do with it, but that's how it would work if I had continued the Shining Force emulation. It's mostly just a matter of how the battle scene gets activated, so I suppose it could still be done -- as long as I can get the "activation" to work easily.

There are a couple more days of work, and then I think it'll be ready to hand off to anyone who wants to use it.

:mrgreen:

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

stuck again

#19 Post by kamiomi »

Well, the manual is missing descriptions and examples of all the menu functions, and I had a hard time translating the custom menu in the Ren'Py demo, so... I'm a little stuck. I actually got the menu working, except for actually GOING to the assigned label.

I tried pretty much copying the menu in the demo, because I had no other example to work with (and the menu shows up, but when I click on any button, it just acts like a "pass" and goes to the next label in the script - instead of going to the labels that should be assigned to the buttons):

Code: Select all

    python:
        battle_knight=[
            ("attack", "Attack"),
            ("strength_up", "Strength Up"),
            ("defend", "Defend"),
            ("use_item", "Use Item"),
            ("run", "Run Away"),
        ]
        battle_rogue=[
            ("attack", "Attack"),
            ("jump_attack", "Jump Attack"),
            ("defend", "Defend"),
            ("use_item", "Use Item"),
            ("run", "Run Away"),
        ]
        battle_wizard=[
            ("attack", "Attack"),
            ("spell", "Cast a Spell"),
            ("defend", "Defend"),
            ("use_item", "Use Item"),
            ("run", "Run Away"),
        ]
        def battle_menu(menuitems):
            renpy.choice_for_skipping()
            ui.vbox(xalign=0.5, ypos=150, yanchor=0.5)
            for label, name in menuitems:
                ui.button(style='button',
                        clicked=ui.returns(label),
                        xminimum=250,)
                ui.text(name, style='button_text',
                        size=16,
                        minwidth=250)
            ui.close()
            rfd = renpy.roll_forward_info()        
            store.result = ui.interact(roll_forward=rfd)
            renpy.checkpoint(store.result)

#then, calling it, later in the script:
$ battle_menu(battle_knight)
I did all the other stuff I said I would do too - now I have it working to call a battle scene from anywhere, which is great, I added other various items, including poison as an item, and a spell (and curing poison) - and I did end up using a "battle narrator" to position the battle text (I didn't know you could choose None, as a character name).

All I need now is to get the menus working (and also, I want to do an 800x600 version as well, but that shouldn't be much of a problem). Any help would be appreciated as usual, at least this time I tried to do it on my own first.

:mrgreen:

Counter Arts
Miko-Class Veteran
Posts: 649
Joined: Fri Dec 16, 2005 5:21 pm
Completed: Fading Hearts, Infinite Game Works
Projects: Don't Save the World
Organization: Sakura River
Location: Canada
Contact:

#20 Post by Counter Arts »

DaFool wrote:That is cool. I'm very tempted to whip up something using this engine and my own graphics. Credit will be given of course! Yay for battle engine contributors (Counter Arts and yourself)

The only issue I see is that it's 1 vs 1 and most scenarios require squad-based tactics.
Sorry about not being able to help you with my engine. Been very busy with preparing to go home to Canada.

You can use that interface with my engine if you wish. I still haven't made my engine non-programmer friendly.

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

#21 Post by DaFool »

Counter Arts -> no worries. I'll see what can be put together in the meantime, but I'll prioritize the other projects first.

kamiomi -> I was thinking of something like Gadget Trial, where you use ui interface to position your pieces, then a condition will set off an individual battle.

But I bet programming that interface will be insane. Maybe a simple menu will suffice in the meantime.

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

#22 Post by kamiomi »

Well, a simple menu would suffice, if it worked. :roll:

For some reason, the clicked=ui.returns(label), isn't working, the buttons are displaying properly, but clicking a button isn't returning anything, so there must be a problem with how I assigned the label...

:?:

User avatar
PyTom
Ren'Py Creator
Posts: 16096
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

#23 Post by PyTom »

Well, you are storing the result of the interact in store.result. What are you doing with this result? You may want to do:

jump expression result

or

call expression result

or something similar.
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

#24 Post by kamiomi »

What I want to do is jump to the label = result. Using ui.jumps(label) instead of ui.returns(label) makes it work, sort of, but it doesn't seem quite right.

I'm running into a worse problem with the spell menu:

I need to jump to a label, assign a text string of the spell's name to the variable "spellname" (which should also be the word appearing on the button text), and assign an integer value to the variable "spelllvl" - all from the python code when the button is clicked.

Maybe the problem is I can't put a text string and an integer value in the same tuple?

Code: Select all

#for example:
        spells3=[
            ("spell_damage", "Spark", 1)
            ("spell_heal", "Heal", 1)
            ("spell_damage", "Blast", 2)
            ("battle_menu", "Cancel", 0)#I don't need the number here, I just assumed they have to be in the same format
        ]

#this is what I tried, but it doesn't work:
        def battlespell_menu(menuitems):
            renpy.choice_for_skipping()
            ui.vbox(xalign=0.5, ypos=150, yanchor=0.5)
            for label, spellname, spelllvl in menuitems:
                ui.button(style='button',
                        clicked=ui.jumps(label),
                        xminimum=250)
                ui.text(spellname, style='button_text',
                        size=16,
                        minwidth=250)
            ui.close()
            rfd = renpy.roll_forward_info()        
            store.result = ui.interact(roll_forward=rfd)
            renpy.checkpoint(store.result)

#and calling it later, in the game (which should work fine):
$ battlespell_menu(spells3)
How do I jump to the first value, assign the second value to the button text and to the variable $ spellname, and assign the integer value to the varialbe $ spelllvl ?

:?:

User avatar
PyTom
Ren'Py Creator
Posts: 16096
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

#25 Post by PyTom »

You probably want to return a tuple using ui.returns.

Code: Select all

        def battlespell_menu(menuitems):
            renpy.choice_for_skipping()
            ui.vbox(xalign=0.5, ypos=150, yanchor=0.5)
            for label, spellname, spelllvl in menuitems:
                ui.button(style='button',
                        clicked=ui.returns((label, spellname, spellevel)),
                        xminimum=250)
                ui.text(spellname, style='button_text',
                        size=16,
                        minwidth=250)
            ui.close()
            rfd = renpy.roll_forward_info()       
            label, store.spellname, store.spelllvl = ui.interact(roll_forward=rfd)
            renpy.checkpoint(store.result)
            renpy.jump(label)
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

#26 Post by kamiomi »

Code: Select all

TypeError: 'tuple' object is not callable
I tried it, and that's what I got. :cry:

User avatar
PyTom
Ren'Py Creator
Posts: 16096
Joined: Mon Feb 02, 2004 10:58 am
Completed: Moonlight Walks
Projects: Ren'Py
IRC Nick: renpytom
Github: renpytom
itch: renpytom
Location: Kings Park, NY
Contact:

#27 Post by PyTom »

Which line is the error on?
Supporting creators since 2004
(When was the last time you backed up your game?)
"Do good work." - Virgil Ivan "Gus" Grissom
Software > Drama • https://www.patreon.com/renpytom

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

#28 Post by kamiomi »

Okay, THAT was just an issue of putting in commas after my tuples :oops:

I had to fix that variable spelllevel, to match my spelllvl - and NOW, it seems to work.

:mrgreen:

kamiomi
Newbie
Posts: 23
Joined: Sun Apr 08, 2007 2:19 am
Contact:

FINISHED!

#29 Post by kamiomi »

Well, for what it is - a proof of concept demo - it's done. At least, I'm done working on it. Not bad for four days of work - with LOTS of help from PyTom, thanks very much!

I'm not sure if there's a better place to post it...

640x480 version - this is the one the graphics and positions are really made for:
http://www.flipdrive.com/file/9856a0b67 ... fd14b9.zip - about 4MB
800x600 version
http://www.flipdrive.com/file/8843c8996 ... 14e2b3.zip - about 5MB

Use:
RPG-style one-on-one combat system, called from any point in the story:

Code: Select all

-The script uses the following variables from the user's RPG story:
playerxp (amount of current xp from 0 to next level)
playerlvl (multiplier for damage and spell effects)
potion, hipotion, shieldpotion, regenpotion, poisonpotion (Inventory items that can be used during 

combat, or found after defeating a monter)
gold (after defeating a monster, there's a chance of receiving gold)

Code: Select all

-Setting up battle scenes:
define battle background images, eg. "image battle village" -- to go with a set of regular 

backgrounds, such as "image bg village1", "image bg village2", etc. any number of regular 

backgrounds can use the same battle background.
- when declaring a scene, or new location in the game, set the following variable:
$ battlebg = "village" #to go with the example, whatever the word is after "battle" in the image 

definition.
ALSO, define which platform the player will stand on (the ones included are "grassy", and "stone" 

- which could apply to a variety of scenes).
$ plat = "stone" #for example - this word is the second word of the image file's name.
To add new platform graphics, name the image file using the following convention: 

"platform_stone.png" and they should probably be the same general size and shape as all others.
--Then any battle called, from that point, will use that background, and that platform, until the 

variables are set to use different images.

Code: Select all

-Characters and Monsters:
character and monster actions may use any of the following poses:
anticipate, crouch, jumping, jumpstrike, recoil, spell_anticipate, spell_cast, stand, strike
-- all creatures need "stand", "anticipate"- preparing to strike, "strike", and "recoil" - after 

being hit, defending, or using an item.
- Image files must be named like the following: "Goblin_stand.png", "Rogue_crouch.png", etc.  The 

"Name" of the creature is the first part of the file name.

-To use a defined player or monster in battle, just set the following variables at some point 

before combat:
$ player = "Knight" #for example
$ enemy = "Goblin" #for example

-To create new monsters or player types - add to the battle script in the label "battle_start", an 

entry like the following:

    if enemy == "Goblin":
        $ enemylvl = 1  #most abilities are multiplied by creature level
        $ enemymaxhp = 40+(10*enemylvl)
        $ enemyhp = enemymaxhp  #initializing the combatant's current HP at maximum
        $ enemydefense = 1
        $ estr = 6 #strength
        $ edex = 4  #dex
        $ earm = 2+enemylvl  #armor
        $ enemyxp = 50 #XP value
        $ epotion = 3 #number of potions or hi-potions in the monster's inventory
        $ ehipotion = 0
        $ eregen = 0  #amount of regeneration of HP each round
        $ eclass = 1 #rogue - jump attack, eclass = 0 will just attack and defend as a fighter
# eclass = 2 is a spell caster who can cast and resist spells, eclass = 3 is immune to poison, and 

can cast poison.  eclass = 4 is a dragon - attack, or cast the spell Blast.

    if player == "Knight":
        $ playermaxhp = 90+(25*playerlvl)
        $ playerhp = playermaxhp   #initializing the combatant's current HP at maximum
        $ playerdefense = 1 #--- this is always 1 at the start of combat (it is changed throughout 

combat to determine the combatant's defensive posture - the "Defend" action raises it, missing an 

attack or using certain special abilities lowers it).
        $ pstr = 8 #strength - attack damage
        $ pdex = 2  #dex - chance to hit or dodge
        $ parm = 4+playerlvl  #armor - reduces damage taken from attacks
        $ pregen = playerlvl  #amount the player type regenerated, in HP, each round
        $ strong = 0 #always 0
        $ pclass = 0 #pclass = 1 is resistance of poison, and more successful poison use
#pclass = 2 is resistance to spell damage.  pclass = 0 has no special resistance

-Note: If a new Player type is created, then a new entry must be added to "label battle_menu:" 

also, to determine what battle_menu the player uses.  These battle menus are defined in the init 

block.  The easiest thing would be to rename the image files, and rename the Knight, Rogue, and 

Wizard to match the image files -- and then other than that use them as they are (I could have 

added a miscellaneous battle menu, if the player name was anything other than "Knight", "Rogue", 

or "Wizard", but I didn't only because I just thought of that right now).

-New spell lists (defined in the init block, and called under "label spell:") can also be created 

- adding completely new spell effects involves editing code, but feel free.

Code: Select all

-Starting a battle:
in the game script, define the following variables at some point before beginning the battle (as 

described above):
player, enemy, battlebg, and plat

then add the following code:

call battle_start

-after the battle is done, it will return to this point in the script, so put any additional 

battle resolution or continuation of the story here.

- To start another battle at the same location, just set player, and enemy, and call battle_start 

-- or change the battlebg, and plat

That's about everything, I think. The various damage or hit calculations could use some tweaking, the amount of experience points for killing monsters is probably too high for a practical use -- and of course, all players use the same experience points (the solution to that would be to set playerlvl or playerxp using some outside condition, based on which character was chosen -- and then after combat, put the values of those variables back into the character's own variables, or something.


As I've said before, this is free for anyone to use/distribute/modify, code, graphics, and all (although, you'd probably want to change the graphics). Anyone who wants to use this in full, or in part, or to edit the heck out of it, can feel free to do so.

No credit is required, but feel free to let me know - I'd love to see if someone gets a use out of it.

:mrgreen:

User avatar
DaFool
Lemma-Class Veteran
Posts: 4171
Joined: Tue Aug 01, 2006 12:39 pm
Contact:

#30 Post by DaFool »

THANK YOU

That's a lot of code now compared to last time. Not to mention the backgrounds are awesome!

I might just have to write a game just to use this engine (and further distract myself from the tasks at hand). Hopefully I'll be able to find an equivalent replacement for each attack / spell so the only thing that needs tweaking is the naming.

Post Reply

Who is online

Users browsing this forum: Google [Bot]