RPG Battle Engine - Alpha 7.5, downloads in first post

A place for Ren'Py tutorials and reusable Ren'Py code.
Forum rules
Do not post questions here!

This forum is for example code you want to show other people. Ren'Py questions should be asked in the Ren'Py Questions and Announcements forum.
Post Reply
Message
Author
Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#91 Post by Jake »

Mole-chan wrote: It works, but the resulting items have no quantity in the new store, and thus can't be sold.
What do you mean by "no quantity in the new store"? If it's just that your shop doesn't have a price for them, could you not just add them to the price list for the shop (if you've written your own shop code, this may be outside of the remit of the battle engine)? If you're using the price list classes in the engine, in fact, you should just be able to set the buyExclusive parameter to False when you create the price list, and they'll be able to buy any item regardless of whether it's on their price list?
DaFool wrote:I'm really wishing for a drag n drop version of the panning code. This would make the Android version more intuitive by making the whole map pannable by swiping.
I actually wrote this a while ago, but since there's been no release of the engine since then, it's not been released. Here's the code:

Code: Select all

    class BattleDragDisplayable(BattleDisplayable):
        
        def __init__(self, threshold, *args, **properties):
            
            super(BattleDragDisplayable, self).__init__(*args, **properties)
            
            self._threshold = threshold
            self._startPos = None
            self._dragPos = None
            self._dragging = False
            self._last = None
            
        def event(self, event, x, y, st):
            
            if (self._last == None):
                self._last = st
            else:
                if (st - self._last < 0.05) and (event.type != pygame.MOUSEBUTTONDOWN) and (event.type != pygame.MOUSEBUTTONUP):
                    return
                else:
                    self._last = st
            
            if (self._dragging == False):
                rv = super(BattleDisplayable, self).event(event, x, y, st)
                if rv is not None:
                    return rv
                    
            if self._dragging:
                
                
                if (self._dragPos != None):
                    
                    prevX = self._dragPos[0]
                    prevY = self._dragPos[1]
                    
                    dx = x - prevX
                    dy = y - prevY
                    
                    battle.CameraX = battle.CameraX - dx
                    battle.CameraY = battle.CameraY - dy
                    
                self._dragPos = (x, y)
            else:
                if (self._startPos != None):
                    dx = math.fabs(x - self._startPos[0])
                    dy = math.fabs(y - self._startPos[1])
                    #dist = math.sqrt((dx*dx)+(dy*dy))
                    
                    dist = dx + dy
                    
                    if (dist > self._threshold):
                        self._dragging = True
                    
                    
            if (event.type == pygame.MOUSEBUTTONDOWN) and (event.button == 1):
                
                self._startPos = (x, y)
                self._dragPos = (x, y)
                
            if (event.type == pygame.MOUSEBUTTONUP) and (event.button == 1):
                
                self._dragPos = None
                self._startPos = None
                
                if (self._dragging):
                    self._dragging = False
                    raise renpy.display.core.IgnoreEvent()
                
                
        def render(self, width, height, st, at):     
            
            return renpy.Render(config.screen_width, config.screen_height)
        
    class DragToPanExtra(Extra):
        
        def __init__(self, threshold=50):
            self._disp = BattleDragDisplayable(threshold)
            
        def Show(self):
            l = self._battle.GetLayer('UI')
            pos = Transform(xpos=0.5, ypos=0.5)
            renpy.show("dragOverlay", what=self._disp, at_list=[pos], layer=l, zorder=999999)
Naturally that's under the same license as the rest of the battle engine. There's a small chance that it doesn't work because it uses things that I've developed as part of the next release which aren't in the last release of the engine, but I don't think so.

If you find that it lags when dragging, then adjust the value on the line:

Code: Select all

if (st - self._last < 0.05) and (event.type != pygame.MOUSEBUTTONDOWN) and (event.type != pygame.MOUSEBUTTONUP):
The 0.05 there is the number of seconds it will ignore further events for after processing the current one - if you try and process all events it's incredibly slow to update while the mouse is moving. I set it to 0.05 because it works fine like that on my dev machine, but I need to test it on some slower machines and preferably my phone before settling on that number.
Server error: user 'Jake' not found

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

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#92 Post by DaFool »

Sweet, thank you!

Hseo
Regular
Posts: 38
Joined: Thu Sep 24, 2009 10:42 am
Completed: High School Life:HSL
Deviantart: greeeed
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#93 Post by Hseo »

was trying to use jump_label for CG event but I can't go back from where I leaved.

Is there anyone to use jump label_name and return back without starting from beginning?
(tried to use call >> return and it send back to end of battle (after python part)

+
Thanks for sharing your code ^^.

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#94 Post by Jake »

Hseo wrote: Is there anyone to use jump label_name and return back without starting from beginning?
(tried to use call >> return and it send back to end of battle (after python part)
If you look at engine-events.rpy (and/or events-demo.rpy) there's some code which allows you to set up event triggers in your battles so that bits of Ren'Py script can be run or changes made to the battle when the player fulfils certain conditions.

In that code, the CallLabelInNewContextResult is used to fire off Ren'Py scenes in the middle of battles. You could use that (there's an example in events-demo.rpy), or you could just call the same Python code:

Code: Select all

    renpy.call_in_new_context("label_name")
and then have a 'return' at the end of your label to go back to the point that call_in_new_context was called.

Essentially what that does is sets up a new Ren'Py context and starts at the label you specify. The downside of running in a new context is that you can't make any changes to your game state in that new context, because they won't be kept when you return to the battle from it - but for an event CG, that shouldn't be a problem. I believe persistent variables and so on are kept from context to context, for example.
Server error: user 'Jake' not found

Hseo
Regular
Posts: 38
Joined: Thu Sep 24, 2009 10:42 am
Completed: High School Life:HSL
Deviantart: greeeed
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#95 Post by Hseo »

Work like charm :mrgreen:
Thank you 8)

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

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#96 Post by DaFool »

Hmmm,

Code: Select all

global name 'pygame' is not defined.
I already imported renpygame, though I don't think that matters.
Shouldn't 'mousedown' or other keybindings supposed to work as well?

Is the draggable pan only supposed to work in RAPT (which has pygame subset for android), or should it work on desktop as well?

Much appreciated. (I'm so behind schedule).

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#97 Post by Jake »

DaFool wrote:

Code: Select all

global name 'pygame' is not defined.
Is the draggable pan only supposed to work in RAPT (which has pygame subset for android), or should it work on desktop as well?
You just need to add this line somewhere above the class definition in the same block:

Code: Select all

    import pygame
Sorry, obviously I've done this in the engine code in the file I've written that class in, and forgot to copy/paste it here.

The dragging code works fine on the desktop for me; I've not actually tested it on Android yet since I don't have Java installed presently, although I can't imagine it's any different. Ren'Py itself is built on pygame, after all.


As to why I referenced those constants out of pygame directly as opposed to renpygame: it's simply that I didn't find any documentation for it in the Ren'Py docs, so I went looking for usage code in Ren'Py itself... and PyTom refers to those consts straight out of pygame. I didn't bother to check whether they're in renpygame as well. ;-)
Server error: user 'Jake' not found

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

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#98 Post by DaFool »

Another thing, the default move in WarGame isn't PathMove, so the fighter maintains the same orientation. Considering that the fighters are usually cards, so it makes sense.

However I really liked the diceroll implementation that's why I'm using it. It's no biggie, since I needed to load up on differing attack skills anyway, so I disabled the section pertaining to basic combined attack/move implementation in WarGame skill.

Also inspired by Fire Emblem, would be nice if AttackSkill can carry a 'cost' variable, doesn't deplete MP, but after certain number of uses the equipment breaks so can't be used anymore unless you can equip something in reserve. Right now I'm looking at treating certain weapons as I would consumeable Potions.

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#99 Post by Jake »

DaFool wrote: Another thing, the default move in WarGame isn't PathMove, so the fighter maintains the same orientation.
Well, the default move skill in Wargame is the WargameSkill, which does move and attack in a single skill; if you also want to select different attack skills, you're probably better off not using WargameSkill at all, and just use separate move and attack skills.

(PathMove in the demos is just an instance of the MoveSkill class with particular options passed in - check in assets.rpy where they're all set up.)
DaFool wrote: However I really liked the diceroll implementation that's why I'm using it. It's no biggie, since I needed to load up on differing attack skills anyway, so I disabled the section pertaining to basic combined attack/move implementation in WarGame skill.
For what it's worth, if you just want the CRT-based combat, then you can just use a CustomSchema and pass in the AttackResolver from the wargame classes. If you wanted to use a turn-based battle with the wargame attack mechanics, for example, you could just set your battle up like this:

Code: Select all

    battle = Battle( CustomSchema(SimpleTurnSchema, attackResolver=WargameAttackResolver) )
DaFool wrote: Also inspired by Fire Emblem, would be nice if AttackSkill can carry a 'cost' variable, doesn't deplete MP, but after certain number of uses the equipment breaks so can't be used anymore unless you can equip something in reserve. Right now I'm looking at treating certain weapons as I would consumeable Potions.
That's probably as good a hack for that as anything in the current release of the engine. In the next release there's an option for equipment to impart skills - so you'll be able to set up a sword with a built-in number-of-uses, which makes the "Attack with sword" skill available... and that skill will be able to check the number of uses and make itself unavailable when the sword is broken. But for now, you'd have to do a fair bit of engine-hacking to add the same functionality, so consumable items is probably the way forward.
Server error: user 'Jake' not found

CaseyLoufek
Regular
Posts: 142
Joined: Sat May 28, 2011 1:15 am
Projects: Bliss Stage, Orbital Knights
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#100 Post by CaseyLoufek »

That's probably as good a hack for that as anything in the current release of the engine. In the next release there's an option for equipment to impart skills - so you'll be able to set up a sword with a built-in number-of-uses, which makes the "Attack with sword" skill available... and that skill will be able to check the number of uses and make itself unavailable when the sword is broken. But for now, you'd have to do a fair bit of engine-hacking to add the same functionality, so consumable items is probably the way forward.
Dangit, why you keep obsoleting my code...

I already did a fair bit of that engine hacking to get equipment that will add attacks to mecha. My system is not perfect so maybe you can help me clean it up a bit, or if you haven't gotten started maybe it's a jumping off point. In any case so I don't feel my time was totally wasted when your version comes out here's mine so far:

Code: Select all

        #New fight equip subclass that stores the fighter for registering skills from items
        class OKFighterEquipment(HandedFighterEquipment):
            def __init__(self, hands=2, limits={'pilot':1}, fighter=None):
                super(HandedFighterEquipment, self).__init__(limits=limits)
                self._hands = hands
                self._fighter = fighter

            def Add(self, item):
                allowed = self.CanBeAdded(item)
                if allowed:
                    self._items.append(item)
                    for s in item._skills:
                        s = s()
                        self._fighter.RegisterSkill( s )
                return allowed
                
            def Remove(self, item):
                allowed = self.CanBeRemoved(item)
                if allowed:
                    self._items.remove(item)
                    for s in item._skills:
                        s = s()
                        self._fighter.UnregisterSkill( s )
                return allowed

Code: Select all

        #New equipment subclass that stores skills and cost
        class OKEquipment(StatBonusEquipment):
            def __init__(self, name='Equipment', bonuses={}, attributes=[],skills=[],cost=25):
                BattleEquipment.__init__(self)
                self._attributes = attributes
                self._bonuses = bonuses
                self._name = name
                self._skills = skills
                self._cost = cost

Code: Select all

        class OKFighterPC(PlayerFighter):
            def ResetStat(self, stat, value): #new 
                setattr(self.BaseStats, stat, value)
                setattr(self.RawStats, stat, value)
                
            # Add a skill to this fighter's list of abilities
            def RegisterSkill(self, skill):
                if (skill.Name in self._skillHandlers) == False:
                    regskill = copy.deepcopy(skill)
                    self._skillHandlers[regskill.Name] = regskill
                    regskill.RegisterFighter(self)
                else:
                    newname = skill.Name+" ||"
                    if (newname in self._skillHandlers) == True:
                        while (newname in self._skillHandlers) == True:
                            newname = newname+"|"
                    regskill = copy.deepcopy(skill)
                    self._skillHandlers[newname] = regskill
                    regskill.RegisterFighter(self,newname)
     
            def UnregisterSkill(self, skill):
                if (skill._name in self._skillHandlers) == True:
                    del self._skillHandlers[skill._name]
                    nests = skill._command[:len(skill._command) - 1]
                    command = skill._command[len(skill._command) - 1]                
                    fs = self.Skills                
                    for s in nests:
                        fs = fs[s[0]][0]
                    del fs[skill._name]
                    if len(fs) < 1: # if we emptied the submenu
                        fs = self.Skills                
                        for s in nests: # go back and find the first empty submenu and clean it
                            if len(fs[s[0]][0]) < 1:
                                del fs[s[0]]
                                break
                            else:
                                fs = fs[s[0]][0]

Code: Select all

        class OKFighterNPC(MovingAIFighter):            
            def ResetStat(self, stat, value): #new 
                setattr(self.BaseStats, stat, value)
                setattr(self.RawStats, stat, value)
                    
            # Add a skill to this fighter's list of abilities
            def RegisterSkill(self, skill, weight=100):
                if (skill.Name in self._skillHandlers) == False:
                    regskill = copy.deepcopy(skill)
                    self._skillHandlers[regskill.Name] = regskill
                    self._skills[regskill.Name] = weight
                    regskill.SetUpFighter(self)
                else:
                    newname = skill.Name+" ||"
                    if (newname in self._skillHandlers) == True:
                        while (newname in self._skillHandlers) == True:
                            newname = newname+"|"
                    regskill = copy.deepcopy(skill)
                    self._skillHandlers[newname] = regskill
                    self._skills[newname] = weight
                    regskill.SetUpFighter(self)
     
            def UnregisterSkill(self, skill):
                if (skill._name in self._skillHandlers) == True:
                    del self._skillHandlers[skill._name]
                    nests = skill._command[:len(skill._command) - 1]
                    command = skill._command[len(skill._command) - 1]                
                    fs = self.Skills                
                    for s in nests:
                        fs = fs[s[0]][0]
                    del fs[skill._name]
                    if len(fs) < 1: # if we emptied the submenu
                        fs = self.Skills                
                        for s in nests: # go back and find the first empty submenu and clean it
                            if len(fs[s[0]][0]) < 1:
                                del fs[s[0]]
                                break
                            else:
                                fs = fs[s[0]][0]
Okay to be fair this sucker didn't take TOO long and most of it was learning the system that I'd needed to do anyway. I'm also not thrilled with the system of Missle, Missle I, Missle II and so on but have yet to think of a better way to handle doubling up.

Still I'm wondering what else is next so I can plan appropriately.

Two major pains I'm about to tackle are a limited turn move system for vehicles so the available spaces are restricted by facing and a system to handle altitude for flyers.

I'm also wondering about greater than 1x1 units, that's probably slightly more universally desired than my crazy vehicle movement.

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#101 Post by Jake »

CaseyLoufek wrote: Dangit, why you keep obsoleting my code...
It's to keep you on your toes! ;-)

(I thought I'd announced that this particular feature was going to be in the last release, so I was already feeling a bit guilty that it didn't get in...

For what it's worth, I've already implemented it; one of the great things about doing a battle-engine project for NaNo is that I am suddenly made painfully aware of all the parts of the engine that really are needed for a proper game, so at the end of NaNo there's a load of extra engine stuff to add to the next release! The approach I took was to separate out on the fighter the list of skills which have been registered against that fighter specifically, and the list of skills which are available to that fighter - so when building the action menu, I look at the latter... but the latter list actually gets rebuilt from the list of skills registered against the fighter and any skills available from any equipment that fighter happens to have at the time. Like this I don't have to unregister skills at any point, because if the fighter loses a bit of equipment or that bit of equipment chooses to stop imparting a skill (e.g. in DaFool's breaking-swords example) then that skill just isn't included next time the fighter's all-available-skills list is rebuilt.

There's nothing particularly wrong with the way you're doing it, mind! The only thing I'd comment on is that I'd been careful to avoid in the most part stuff like copying skill or - particularly - equipment or item instances, and instead having all references to a particular item go back to the same instance of the item. Obviously separate instances are necessary for things like the breaking-weapons which need to maintain some sort of state, but for the most part it's useful to be able to check whether two items or bits of equipment are 'the same' simply by doing a reference comparison rather than having to check whether they have the same name or other properties. The shop and equip screens in particular rely on this to aggregate items & equipment.
CaseyLoufek wrote: I'm also not thrilled with the system of Missle, Missle I, Missle II and so on but have yet to think of a better way to handle doubling up.
Is this because you're representing ammunition with separate pieces of disposable equipment?
CaseyLoufek wrote: Still I'm wondering what else is next so I can plan appropriately.
In terms of breaking changes - not much. The things that I've already done or am part-way through for the next release are as follows:
- Some utility methods on Battlefield instances to get at positions more easily
- RemoveFighter method on Battle
- Get/Set overrides in equipment and extras for base stats as well as just regular stats (an embarrassing omission that I only noticed when I tried to add body-armour equipment in my current game and couldn't get it to register a base armour above the fighter's 0!)
- Vehicles
- Callback param to AttackResolver so the skill can do things based on the results of the attack (this is a breaking change, but a minor one)
- Sprites, Targets, Skills, Fighters, Battlefields, Battles, Items, Equipment, Inventory now definable via Ren'Py script extensions
- Various new classes to support the above which can also be useful as generic base classes for custom equipment/skills/etc.
- Various *Builder classes to create generic create-me-a-template-* classes.
- Added DragToPanExtra to facilitate mobile devices etc.
- Equipment can now impart skills to fighters who equip it
- Level-ups can now add skills
- New FighterGainSkill and FighterLoseSkill events on BattleAware
- Positions having attributes which may - for example - affect the movement rates through that terrain, or whatever.

I'm still not sure about items imparting skills; part of me says I should do it, and perhaps even replace the existing item skill with a default "Items->Use This Item" skill that the item itself adds... part of me says that like that, Items almost lose their distinction from Equipment anyway, and they don't need skills.

That's all the stuff that's more or less ready to release in the next version of the engine... and to be honest, there's not too many breaking changes there, and I don't see any future stuff that needs significant changes to the structure, so the next release may well be the first beta. Which to my method of labelling, means that it should be stable enough to not need any more breaking changes, any future development should be able to build off of the existing engine without requiring changes to people's existing game code. (Barring, of course, any changes to Ren'Py significant enough that they would also require people to make changes to their existing game code.)
CaseyLoufek wrote: Two major pains I'm about to tackle are a limited turn move system for vehicles so the available spaces are restricted by facing and a system to handle altitude for flyers.
Limited turn radius is something that I've thought about myself, but while I may at some point do an example skill class, it probably doesn't need special engine support... I suspect the rational way to do it would be to have the MoveSkill target all positions within <move points> range, and then use the FilterTargets method to cut the options down based on the current facing of the unit. Or simply have your vehicle move skill require that the user repeatedly selects a move target for each step of the movement!

The only way the engine could realistically support something like that is by passing the facing it used to get to a particular spot into the callback for move steps... and that would dramatically increase the amount of number-crunching necessary in the pathfinding code, because it would have to process each position multiple times for multiple potential entry directions.


As to flyers... the simplest way I can think of to do that would be to:
- modify the flyer's Height stat as they move up and down, as LoS is drawn from and to the fighter's Height stat above the ground they're standing on*
- subclass the Fighter to modify the Fighter's Anchor/Placemark accordingly, so that the sprite and target buttons and so on show up in the right place.

* bearing in mind that fighters are 1 unit tall by default, and this represents however many pixels of height that you define in your battlefield's heightStep parameter (default 100pixels).

(Of course, I think every tactics game I've seen represents flyers as units with a special move that lets them ignore terrain, but still lands after the end of each move!)
CaseyLoufek wrote: I'm also wondering about greater than 1x1 units, that's probably slightly more universally desired than my crazy vehicle movement.
I've also been wondering about multi-space larger units! I'm really not sure whether I want to support them or not, simply because there's a lot of questions that they elicit, and I'm not sure if I can provide either customisation or a generally-useful answer to all of them. Things like:
- How does LoS work - do you just need LoS to one of the squares occupied, or all of them, or should the fraction of LoS you have be calculated by the fraction of the fighters' squares you can see?
- What counts as the position the fighter is at for drawing LoS from that fighter?
- How does movement work - do you need a path at least fighter-width wide to move through, or can you move through narrower gaps?
- Do non-square units need to be supported, and how does that interact with facing and moving through gaps?
- Would people be willing to provide a separate sprite for each square the fighter occupies, or do I have to re-order everything on an elevation map every single time the fighter moves to ensure that all the surrounding terrain is drawn with the correct z-index?

...and so on. The simplest answer would be to support only square units an odd number of squares in width, because then I could simply treat them as a point with a radius and half of those questions would be simplified away... but I'm not sure that's incredibly more useful than just having 1x1 as an option, when the next largest size is literally nine times the square occupancy!
Server error: user 'Jake' not found

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

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#102 Post by DaFool »

I'm trying to insert an insta-kill whenever the attacker is directly behind the target (meaning, they're both facing the same direction).

I tried inserting this code somewhere in the attack resolver (before it, er, even starts to resolve)

Code: Select all

            if target.GetFacing == fighter.GetFacing:
                _battle.Announce("6 O'Clock perfect Shot!")
                self.kill(target, attacker)
GetFacing or facing is not an attribute of PlayerFighter... hmmm if I recall correctly the facing states are attributes of the image sprites themselves, so that means I have to grab the current sprite that's being used, then get the current facing from that?

Also (this is not so important though would be aesthetically nice) is there a way for pygame to draw a line tracing the player fighter to the target position? Then I can place an arrowhead on the target position and it would look... cool. But that's it, I guess.

A teaser on my current Nano project, which is going to be delayed at least a month or two the rate I barely get anything done despite programming nonstop. My aim is to achieve a 'Nintendo 3DS' level of quality.
Image

Jake
Support Hero
Posts: 3826
Joined: Sat Jun 17, 2006 7:28 pm
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#103 Post by Jake »

DaFool wrote: I tried inserting this code somewhere in the attack resolver (before it, er, even starts to resolve)

Code: Select all

            if target.GetFacing == fighter.GetFacing:
                _battle.Announce("6 O'Clock perfect Shot!")
                self.kill(target, attacker)
GetFacing or facing is not an attribute of PlayerFighter... hmmm if I recall correctly the facing states are attributes of the image sprites themselves, so that means I have to grab the current sprite that's being used, then get the current facing from that?
It's just a property called 'Facing'. So you need something like:

Code: Select all

            if target.Facing == fighter.Facing:
                _battle.Announce("6 O'Clock perfect Shot!")
                self.kill(target, attacker)
instead.
DaFool wrote: Also (this is not so important though would be aesthetically nice) is there a way for pygame to draw a line tracing the player fighter to the target position? Then I can place an arrowhead on the target position and it would look... cool. But that's it, I guess.
...yes, but you'll need to do a bit of work for it.

Basically, you'll need to:

- get the start and end positions (Position property on Fighter, for example) and get their transform xpos and ypos params to get coords
- create a custom displayable, passing in the coords
- in the render method, create a Render which is as wide and as tall as the screen
- use the .canvas.draw.line method on that render to draw the line
- show your custom displayable in the middle of the screen, passing in the result of BattleDisplay.GetPanningTransform() in the transform list to ensure that it pans correctly.



Also, someone should give Fang there a basic lesson in geography. :P
Server error: user 'Jake' not found

CaseyLoufek
Regular
Posts: 142
Joined: Sat May 28, 2011 1:15 am
Projects: Bliss Stage, Orbital Knights
Contact:

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#104 Post by CaseyLoufek »

Ooh, position attributes will be nice.
Jake wrote: Is this because you're representing ammunition with separate pieces of disposable equipment?
I like your way of handling it. My issue is that a unit in the game can have more than one missile launcher or gun equipped. So in the skills menu the player sees them listed with numerals since the names needed to be unique. Really more of a GUI than a core engine issue at this point.
CaseyLoufek wrote: Two major pains I'm about to tackle are a limited turn move system for vehicles so the available spaces are restricted by facing and a system to handle altitude for flyers.
Limited turn radius is something that I've thought about myself, but while I may at some point do an example skill class, it probably doesn't need special engine support... I suspect the rational way to do it would be to have the MoveSkill target all positions within <move points> range, and then use the FilterTargets method to cut the options down based on the current facing of the unit. Or simply have your vehicle move skill require that the user repeatedly selects a move target for each step of the movement!

The only way the engine could realistically support something like that is by passing the facing it used to get to a particular spot into the callback for move steps... and that would dramatically increase the amount of number-crunching necessary in the pathfinding code, because it would have to process each position multiple times for multiple potential entry directions.
I was planning to subclass the MoveSkill to check facings and only add paths if the direction is within an angle. It's probably more intensive but in a turn based game with such small grids I'm not terribly concerned. Even on mobile I wouldn't expect problems.

As to flyers... the simplest way I can think of to do that would be to:
- modify the flyer's Height stat as they move up and down, as LoS is drawn from and to the fighter's Height stat above the ground they're standing on*
- subclass the Fighter to modify the Fighter's Anchor/Placemark accordingly, so that the sprite and target buttons and so on show up in the right place.

* bearing in mind that fighters are 1 unit tall by default, and this represents however many pixels of height that you define in your battlefield's heightStep parameter (default 100pixels).

(Of course, I think every tactics game I've seen represents flyers as units with a special move that lets them ignore terrain, but still lands after the end of each move!)
Yeah, but I'm trying for a high realism setting. That's basically what I had in mind but I want to track the height modifer seperately so I can get their cover and such properly. Also how they interact with terrain height will need to be changed in their MoveSkill since they can treat anything they are over as flat.
- How does LoS work - do you just need LoS to one of the squares occupied, or all of them, or should the fraction of LoS you have be calculated by the fraction of the fighters' squares you can see?
- What counts as the position the fighter is at for drawing LoS from that fighter?
- How does movement work - do you need a path at least fighter-width wide to move through, or can you move through narrower gaps?
- Do non-square units need to be supported, and how does that interact with facing and moving through gaps?
- Would people be willing to provide a separate sprite for each square the fighter occupies, or do I have to re-order everything on an elevation map every single time the fighter moves to ensure that all the surrounding terrain is drawn with the correct z-index?
I would go with fractional LoS, it's the most logical method.

The position for THEIR LoS is trickier. For my game I may want to be able to trace each seperately for different conditions.

For movement, I have the answer: http://harablog.wordpress.com/2009/01/2 ... thfinding/ Some units might be able to slip through areas they could not stand in, but that seems like a special power.

I would personally love non-square units but their pathfinding could be a pain. Also while "square" units can basically be handled the same for hex non-square units would require totally different subclassing or a much more advanced system to handle both.

Single sprite support would be easiest, particular if multiple was an option, but I think if you support this you can demand a little extra effort from end users if it saves a lot of trouble.

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

Re: RPG Battle Engine - Alpha 7.5, downloads in first post

#105 Post by DaFool »

Jake wrote:It's just a property called 'Facing'.
Thank you, the game compiles, but the actual value remains elusive. I can never have the comparison trigger upon runtime. Upon examining the values, they appear to each have some unique hexadecimal value in renpy store.

I wish to retrieve values similar to "n", "ne", "sw", etc. or even just the angles, then they would be ready non-floating-point values that would easily compare to each other.

I can also never get the correct syntax to use GetAngleFromFacing from within an AttackResolver. I always get KeyError:<store.BattleGridPosition object at 0xHexadecimal value

Post Reply

Who is online

Users browsing this forum: No registered users