Using variables in equations for a pseudo-RPG effect

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.
Post Reply
Message
Author
User avatar
Ixis
Newbie
Posts: 17
Joined: Thu May 27, 2010 4:12 pm
Contact:

Using variables in equations for a pseudo-RPG effect

#1 Post by Ixis »

Hi, I'll explain everything from the top-down to give you an idea of what I'm trying to do since I'm pretty sure I might be going at this the wrong way.

Ok, so I want a semi-RPG effect for my game, but I don't want to actually make an RPG. Basically, at certain points in the story the player will be given choices and some choices have a random element to them. You roll dice and add the applicable attribute. If the sum total meets or exceeds a certain value then the character succeeds at the task, failure and something bad happens.

i.e., the player is faced with a locked door. There's a choice to bash the door in or open the door with lockpicks. If the player selects to bash the door in, the game rolls some dice and adds the strength value. If the player selects to use lockpicks then the game rolls the dice, and adds the dexterity value.

The dice rolled should be 3 six-sided die. The attribute changes depending on the circumstances, but the values rarely ever change.

So far I've written the code like this,

Code: Select all

label lockeddoor:
    if hitpoints <=1:
        "Fighter collapses from exhaustion."
        jump end   

menu:
    "The door is locked. Fighter has %(hitpoints)d HP left."
    
    "Pick the lock":
        "Fighter attempts to pick the lock."
        
        $ d6dex = renpy.random.randint(1, 6)
        $ d6dex += 2
        
        if d6dex >= 8:
            "Fighter rolled [d6dex]."
            "As Fighter manipulates the tumbler, he hears the lock open with a satisfying click."
            jump dooropen
        else:
            "Fighter rolled [d6dex]."
            "Fighter failed to pick the lock. Try again?"
            jump lockeddoor
        
    "Bash the door in":
        "Fighter steps back and gets a running start at the door."
        
        $ d6str = renpy.random.randint(1, 6)
        $ d6str += 4
        
        if d6str >= 8:
            "Fighter rolled [d6str]."
            "POW!! Fighter did [d6str] damage!" with vpunch
            jump dooropen
        else:
            "Fighter rolled [d6str]."
            "Fighter attacks the door with all his might! The door is unmoved."
            "Fighter was bruised in the attempt, and took 1 damage."
            $ hitpoints -= 1
            jump lockeddoor
As you can see, there's three problems with this approach.
  1. I can't roll 3 six-sided die. Instead I'm just rolling one die and adding a static attribute value.
  2. I can't use variable attributes. I don't know how to set an attribute and then call it or manipulate it. I'd like to set strength to equal (for example) 4, but then later if Fighter does something to increase his strength set it higher, or maybe he gets poisoned, which would lower it.
  3. The code gets really cumbersome. It means that I have to write up all of the code for what happens when the dice are rolled and all of the immediate reactions to those dice being rolled. If possible, I'd like to have a ".rpy" sheet with all of the attribute info and dice rolling functions. Then, should the game need dice to be rolled, I could use a call to have the game roll the dice and add the right attribute value together. From that point I can write the if/else/elif functions into the script.
So does anyone think they can help me? Thanks in advance.

User avatar
trooper6
Lemma-Class Veteran
Posts: 3712
Joined: Sat Jul 09, 2011 10:33 pm
Projects: A Close Shave
Location: Medford, MA
Contact:

Re: Using variables in equations for a pseudo-RPG effect

#2 Post by trooper6 »

Okay, I've done some of this for you. There are a couple of ways to do this...as usual. First things first. I'd create a die rolling function and a skill roll function.

You can put this code before your start label:

Code: Select all

init -1 python:
    def dieRoll(dice, sides):
        total = 0
        for x in xrange(dice):
            total += renpy.random.randint(1, sides)
        return total
        
    def skillRoll(skill):
        return skill + dieRoll(3,6)
The die roll allows you to make any sort of die roll you want, with any number of die, and it returns the result.
The second function allows you to make a 3d6 roll and add some skill number you specify and returns the result.

If you wanted to roll 6d10, for example, you'd type:

Code: Select all

$ roll = dieRoll(6, 10)
This puts the result in the roll variable.

If you want to have a 3d6 + a Strength of 5 skill roll, you'd type:

Code: Select all

$ roll = skillRoll(5)
That is how the functions work. So how do you do incorporate this into your example? There is a basic way and a more complicated way. For both ways I changed a few of your numbers to make the probabilities a bit more interesting. Specifically, I changed the roll you need to make from 8 (which is really easy to achieve on 3d6 plus a skill number) to 15 (which should be more of a challenge). I gave your menu a label so you can jump to that menu again. I also made it so that if you bash the door you take damage no matter what--so there is some risk in doing that. I also gave the door some hit points so that you can do damage to the door but not open it completely in the first go.

So here is the simple version. At start you declare your Fighter's information, you come upon the door and set the door's HP, then you go into your door menu.

Code: Select all

label start:
    $ FighterST = 4
    $ FighterDX = 2
    $ FighterHP = 5

    "You come upon a wooden door"
    $ doorHP = 20
    jump lockedDoorChoice
    
    menu lockedDoorChoice:
        "The door is locked. Fighter has [FighterHP] HP left. The door has [doorHP] left."
        
        "Pick the lock":
            "Fighter attempts to pick the lock."
            $ roll = skillRoll(FighterDX)
            if roll >= 15:
                "Fighter rolled [roll]."
                "As Fighter manipulates the tumbler, he hears the lock open with a satisfying click."
                jump dooropen
            else:
                "Fighter rolled [roll]."
                "Fighter failed to pick the lock. Try again?"
                jump lockeddoor
            
        "Bash the door in":
            "Fighter steps back and gets a running start at the door."
            $ roll = skillRoll(FighterST)
            if roll >= 15:
                "Fighter rolled [roll]."
                "POW!! Fighter did [roll] damage to the door and 1hp damage to himself!" with vpunch
                $ doorHP -= roll
                $ FighterHP -= 1
            else:
                "Fighter rolled [roll]."
                "Fighter attacks the door with all his might! But all he gets for his attempts is bruising and 2hp damage."
                $ FighterHP -= 2
            if doorHP > 0:
                jump lockeddoor
            else:
                jump dooropen

    label dooropen:
        "The door opens!"
        jump end
    label lockeddoor:
        if FighterHP <= 1:
            "Fighter collapses from exhaustion."
            jump end
        else:
            jump lockedDoorChoice
    label end:
        "The story is over" 
Now, I prefer to make it a bit more complicated at the beginning in order to make it a bit easier later. So I would create a Fighter class like so, which I would put in the file before the start label:

Code: Select all

init -1 python:
    class Fighter:
        def __init__(self, name, a, b, c):
            self.name = name
            self.st = a
            self.dx = b
            self.hp = c
So we can make any number of fighters with different stats just by initializing them like so:

Code: Select all

$ FighterJack = Fighter("Jack", 4, 2, 5)
Anyhow, this is Option B. How the code would look if you are using classes.

Code: Select all

label start:
    $ FighterJack = Fighter("Jack",4,2,5)

    "You come upon a wooden door"
    $ doorHP = 20
    jump lockedDoorChoice
    
    menu lockedDoorChoice:
        "The door is locked. Fighter has [FighterJack.hp] HP left. The door has [doorHP] left."
        
        "Pick the lock":
            "Fighter attempts to pick the lock."
            $ roll = skillRoll(FighterJack.dx)
            if roll >= 15:
                "Fighter rolled [roll]."
                "As Fighter manipulates the tumbler, he hears the lock open with a satisfying click."
                jump dooropen
            else:
                "Fighter rolled [roll]."
                "Fighter failed to pick the lock. Try again?"
                jump lockeddoor
            
        "Bash the door in":
            "Fighter steps back and gets a running start at the door."
            $ roll = skillRoll(FighterJack.st)
            if roll >= 15:
                "Fighter rolled [roll]."
                "POW!! Fighter did [roll] damage to the door and 1hp damage to himself!" with vpunch
                $ doorHP -= roll
                $ FighterJack.hp -= 1
            else:
                "Fighter rolled [roll]."
                "Fighter attacks the door with all his might! But all he gets for his attempts is bruising and 2hp damage."
                $ FighterJack.hp -= 2
            if doorHP > 0:
                jump lockeddoor
            else:
                jump dooropen

    label dooropen:
        "The door opens!"
        jump end
    label lockeddoor:
        if FighterJack.hp <= 1:
            "Fighter collapses from exhaustion."
            jump end
        else:
            jump lockedDoorChoice
    label end:
        "The story is over"
Remember for any of the two code options to work you need to declare the functions and, if using it, the class before the start block in an init block.

To you last question--how do you change variables? The code I posted has examples of changing the hp of the door and the fighter. You would change strength similarly.

If using option a and you want to give the Fighter +2 Strength, you write:

Code: Select all

$ FighterST += 2
If using Option B and you want to give FighterJack +2 Strength, you write:

Code: Select all

$ FighterJack.st += 2
A Close Shave:
*Last Thing Done (Aug 17): Finished coding emotions and camera for 4/10 main labels.
*Currently Doing: Coding of emotions and camera for the labels--On 5/10
*First Next thing to do: Code in all CG and special animation stuff
*Next Next thing to do: Set up film animation
*Other Thing to Do: Do SFX and Score (maybe think about eye blinks?)
Check out My Clock Cookbook Recipe: http://lemmasoft.renai.us/forums/viewto ... 51&t=21978

User avatar
Ixis
Newbie
Posts: 17
Joined: Thu May 27, 2010 4:12 pm
Contact:

Re: Using variables in equations for a pseudo-RPG effect

#3 Post by Ixis »

Thanks! I'll try this out!

Post Reply

Who is online

Users browsing this forum: No registered users