Eiliya wrote:Let's see if I got this right...
I start by placing the init python: statement in much the same way as I do with a regular init: statement (what's the difference between these two, by the way?), and then define the call within that. Then I create an empty list of actors in the form of default actors = {}, which can then be filled with the relevant actors through the statements mentioned below the start label.
So if I were to make this in my own code, it would look something like this?
Code: Select all
init python:
class Creature(object): #why is there object within the ()?
def __init__(name, . . . act):
self.name = name
.
.
.
self.act = act
default actors = {}
label start:
#lots of events leading up to the apes attacking through the door
$ actor = Creature("Noir" . . . 3)
$ actors[actor.Noir] = actor
$ actor = Creature("Abyssal Ape" . . . 1)
$ actors[actor.Ape1] = actor
$ actor = Creature("Abyssal Ape" . . . 1)
$ actors[actor.Ape2] = actor
...
And this would then set the proper stats for the various actors based on the values defined in the script according to the Creature class and then fill the actors into the empty list? If I'm misunderstood anything, please let me know
init is what you can use with Ren'Py statements of any kind (image declarations, screens, styles, constants and etc.). init code will be ran every time the engine is started/rebooted. You can read more about it in the Docs. The part you wrote after label start is different from the example in my code and is likely to crash your game.
or
for one liners expects Python statements.
I don't know what you mean by "define a call within that". You don't create a list, it's called a dictionary, but you can use a list of you please. I would also like to point out that it is a good form not to use abbreviations for attributes, "attack" should be called attack. It's more of a general guideline than a rule but you'll be better off doing that in the long run. It's ok to abbreviate really long and complex names of attributes or variables, but you still want to leave a comment at the original declaration.
ensures that new style classes are used (might be a case with Ren'Py by default, I don't remember). It will never hurt you or your code and will make sure that the game is functioning properly and that you can use all the features of Ren'Py and new style Python classes. Basically you just put it there even if you don't understand why.
Eiliya wrote:
xela wrote:I usually use JSON format to create data and a function to load it into dict, code is very clean that way.
And what is the JSON format, if I may be so stupid as to ask?
https://en.wikipedia.org/wiki/JSON
Don't bother with it for now, we allow hundreds of characters, items and etc. in our game so we're using it, you should be ok with just a few chars, keep it in the back of your mind as a simple, convenient way to store/prepare data for your game. This is an example of (part) of a file we use:
Code: Select all
[
{
"id": "Leather Cape",
"desc": "A humble cloak of oily leather, well suited to the rigors of the road.",
"icon": "content/items/cape/lc.png",
"price": 30,
"sex": "unisex",
"chance": 80,
"badness": 80,
"eqchance": 10,
"hidden": false,
"infinite": true,
"slot": "cape",
"type": "armor",
"max": {"defence": 5},
"mod": {"defence": 5},
"locations": ["Work Shop", "Look around"]
},
{
"id": "Mantle of the Healer",
"desc": "These mantles are mainly used by acolyte healers. They provide additional spirit energy for good deeds, and they are heavy as hell.",
"icon": "content/items/cape/mh.png",
"price": 140,
"sex": "unisex",
"chance": 70,
"badness": 75,
"eqchance": 11,
"hidden": false,
"infinite": false,
"slot": "cape",
"type": "other",
"max": {"mp": 30, "vitality": -20, "agility": -10},
"locations": ["Tailor Store", "Exploration"]
},
{
"id": "Mantle of the Keeper",
"desc": "It's no easy thing to see a Keeper, especially one who does not wish to be seen.",
"icon": "content/items/cape/mk.png",
"price": 4000,
"sex": "unisex",
"chance": 1,
"badness": 0,
"eqchance": 100,
"hidden": true,
"infinite": false,
"slot": "cape",
"type": "other",
"max": {"mp": 200, "magic": 70, "agility": 30, "luck": 20, "intelligence": 15, "health": 20},
"mod": {"magic": 100, "agility": 40, "luck": 30, "intelligence": 20},
"locations": ["Exploration"],
"goodtraits": ["Dandere"]
},
{
"id": "Battle Cape",
"desc": "This cape was reinforced by magic to provide advantages in battle.",
"icon": "content/items/cape/bc.png",
"price": 150,
"sex": "unisex",
"chance": 60,
"badness": 75,
"eqchance": 15,
"hidden": false,
"infinite": false,
"slot": "cape",
"type": "armor",
"max": {"defence": 25},
"mod": {"defence": 40},
"mod_skills": {"refinement": [-0.01, 0, -0.02, 0, 0], "service": [-0.01, 0, -0.01, 0, 0]},
"locations": ["Work Shop"]
},
{
"id": "Elven Cape",
"desc": "Comfortable and noiseless cape from an unknown, soft material.",
"icon": "content/items/cape/ec.png",
"price": 400,
"sex": "unisex",
"chance": 30,
"badness": 20,
"eqchance": 90,
"hidden": false,
"infinite": false,
"slot": "cape",
"type": "armor",
"max": {"defence": 15, "agility": 15},
"mod": {"defence": 35, "agility": 20},
"mod_skills": {"refinement": [0, 0, 0.02, 0, 0], "exploration": [0, 0, 0.02, 0, 0]},
"locations": ["Exploration"],
"goodtraits": ["Not Human"]
},
{
"id": "Linen Capelet",
"desc": "Simple piece of fabric to warn up cold shoulders in unpleasant weather.",
"icon": "content/items/cape/lcl.png",
"price": 90,
"sex": "female",
"chance": 90,
"badness": 80,
"eqchance": 10,
"hidden": false,
"infinite": true,
"slot": "cape",
"type": "dress",
"max": {"charisma": 2},
"mod": {"charisma": 5},
"locations": ["Tailor Store", "Look around"]
},
...
it has a number of advantages if you for example wish to allow people to easily add items to your game, almost everyone knows JSON or can find out about it and validate their file. Same thing can be done with Python but you might invite more questions. Also if you have a few hundreds of these, Ren'Py will not scan this files on every startup. It will if you do the same in .rpy files.
Eiliya wrote:
As for the attack and defense values, here's how I want it to work. The attacker performs the attack while the defender performs the defend (obviously). These two numbers are generated in exactly the same way, except that the non-random number used for them is different (att for the attacker and def for the defender). You start by generating the result of the random value, which you mentioned previously should be done by a python for loop. There needs to be two random numbers generated, one for the attacker and one for the defender. Onto these values we then add the att and def respectively, before we perform the final check to see if any of these reach the upper limit.
Once we have the final results for these values figured out, we compare them to see if the attack is a hit or not, as well as how much damage it inflicts. I took the code you provided and did some modifications according to how I figure it might work, but if this if flawed, please let me know how and why.
Code: Select all
def result(attacker, defender)
attack = dice() + attacker.att # if dice is a func
if attack > x and attacker.lvl < 75:
attack = 400
elif attack > y and p1_lvl < 50:
attack = 320
defend = dice() + defender.def
if defend > x and defender.lvl < 75:
defend = 400
elif defend > y and defender < 50:
defend = 320
result = attack - defend
return result
It is flawed because you still haven't replaces x and y with anything meaningful. Also there should not be "p1_lvl"... there could be attacker.lvl or defender.lvl. You pass two objects to this function, one object is an instance of the defender, other is the attacker. They carry all the data you've entered into them or changed/added during gameplay. That is what you use... and you access it through fields like:
Code: Select all
attacker.name
defender.hp
attacker.level
defender.image
attacker.portrait
and etc.. you don't have/need all the fields but this is an example.
Eiliya wrote:xela wrote:As a rule, you generally learn basic Python first, from Code Academy or Tutorials Point or something like that. Then read through Ren'Py Docs and maybe even glance through Python's docs really fast.
I think I mentioned it before, but doing things that way is completely meaningless for me. Even when faced with the most basic of python, I get stuck on things that I do not understand and have to ask someone to provide a more easy to understand explanation. For example, I went to Tutorials Point to check for the Python for Loop that you mentioned, and was faced with a wall of text containing words I didn't understand, code that make no sense to me, code that contains functions I don't know why they are there and strange lists and diagrams.
There are two simple things you need to setup first:
1) Install Python 2.7.8 and learn how to use IDLE. It's an awesome interface where you can test out Python code that you don't understand.
2) Figure out how to use Ren'Py's console and how to check your data structure with it. Like you can type into console: actors, and you'll see what that looks like so you can understand it better. Later you'll figure out how to do stuff like: actors["Noir"].name or actors["Noir"].__dict__ and etc.
And all of it will look strange, until you've messed with it enough so it doesn't. There is no way you can keep asking base questions, even if you get answers, you'll never know any nuances cause noone will retype docs for you and knowing just a few things is not a good option if you're planning to make complex games.
Eiliya wrote:And then we have the code you showed (I took the freedom to modify it a little).
Code: Select all
init python:
def dice():
return renpy.random.randint(1, 100)
def critical_dice():
result = 0
d = dice()
if d < 3:
result = d - dice()
else:
result += d
if d > 90:
for i in [91, 93, 95, 97, 99]:
d = dice()
if d > i:
result += d
else:
break
return result
Now this. This makes sense. First we have a function
dice which returns the result of the renpy.random.randint function. Then we have the
critical_dice which starts by creating the variable result and setting it to 0. It then creates the variable d and connects it to the dice function, which gives d a value between 1 and 100. Then it checks if that value is below 3, which gives the result of d - dice (I'm guessing a new dice is generated here, since the dice() function is mentioned/called). If the result is something else (above 2, in other words), the function then adds the value from d to result, and then checks to see if d is above 90.
Now this is where things get messy for me. I know that the for i in [numbers] means that the code checks for these numbers when making the loop, but I don't understand what the i or the in stands for. Judging from the rest of the code, I'm assuming the i is a new variable that changes it's value (which is taken from the string within the []) each time it loops, starting at the left number and moving towards the right, but I'm not quite sure what part of the code actually makes it loop.
Anyways, I am too tired to properly think on this matter any further tonight, so I will end it with this post. When I return tomorrow, I'll look over any possible replies, and then shuffle around a bit on Tutorial Point trying to make some sense of things over there, but I'm quite sure I'll come back here to ask for further information and clarification in the end. Thanks for all the help thus far, everyone, and I wish you all a good night.
Eiliya wrote:And then we have the code you showed (I took the freedom to modify it a little).
Code: Select all
init python:
def dice():
return renpy.random.randint(1, 100)
def critical_dice():
result = 0
d = dice()
if d < 3:
result = d - dice()
else:
result += d
if d > 90:
for i in [91, 93, 95, 97, 99]:
d = dice()
if d > i:
result += d
else:
break
return result
Now this. This makes sense. First we have a function
dice which returns the result of the renpy.random.randint function. Then we have the
critical_dice which starts by creating the variable result and setting it to 0. It then creates the variable d and connects it to the dice function, which gives d a value between 1 and 100. Then it checks if that value is below 3, which gives the result of d - dice (I'm guessing a new dice is generated here, since the dice() function is mentioned/called). If the result is something else (above 2, in other words), the function then adds the value from d to result, and then checks to see if d is above 90.
So far so good
Eiliya wrote:
Now this is where things get messy for me. I know that the for i in [numbers] means that the code checks for these numbers when making the loop, but I don't understand what the i or the in stands for. Judging from the rest of the code, I'm assuming the i is a new variable that changes it's value (which is taken from the string within the []) each time it loops, starting at the left number and moving towards the right, but I'm not quite sure what part of the code actually makes it loop.
Well... it's called a for loop, so "for" makes the loop
You got the rest right... i is a variable, you could have written:
but once again, after you get IDLE/console, you do stuff like this:
Code: Select all
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for AbraCaDabRa in range(10):
AbraCaDabRa += 78
print AbraCaDabRa
78
79
80
81
82
83
84
85
86
87
Code: Select all
>>> class Actor(object):
def __init__(self, name, hp):
self.name = name
self.hp = hp
>>> actors = {}
>>> actor = Actor("Noir", 100)
>>> actors[actor.name] = actor
>>> actor = Actor("Player", 100)
>>> actors[actor.name] = actor
>>> actors
{'Player': <__main__.Actor object at 0x02FBFEB0>, 'Noir': <__main__.Actor object at 0x02EBD850>}
>>> actors["Player"]
<__main__.Actor object at 0x02FBFEB0>
>>> actors["Player"].name
'Player'
>>> actors["Player"].hp
100
>>> player = actors["Player"]
>>> player
<__main__.Actor object at 0x02FBFEB0>
>>> player.hp
100
>>> player.hp += 100
>>> actors["Player"].hp
200
>>> player.hp
200
>>> actors["Noir"]
<__main__.Actor object at 0x02EBD850>
>>> actors["Noir"].__dict__
{'hp': 100, 'name': 'Noir'}
>>>
You will instantly see what you're doing, get errors which you can fix right on the next input line and test all the gibberish you don't understand until it makes perfect sense to you. This is exactly how I learned, asking questions invited more and more questions until I figured out that I can get answers even to the most complex questions online, test them until I understand what's going on and implement them into the game/code design.
Eiliya wrote:
Anyways, I am too tired to properly think on this matter any further tonight, so I will end it with this post. When I return tomorrow, I'll look over any possible replies, and then shuffle around a bit on Tutorial Point trying to make some sense of things over there, but I'm quite sure I'll come back here to ask for further information and clarification in the end. Thanks for all the help thus far, everyone, and I wish you all a good night.
Yeap, be sure to test stuff you find on TP in IDLE. You'll learn 10x as much while testing and exploring than from reading the texts.