ID:158040
 
I have a final fantasy project and I was thinking if i could make the battle system just almost similar to final fantasy XII which is real time as well as turn based but, unfortunately, i tried to code it and it seems to fail and it crashed my byond.

I was wondering if anyone could help me in coding the battle system.
Check all of the loops in your battle system very closely to find conditions under which a loop will loop infinitely without a delay.
In response to Nielz (#1)
mob
Enemy
icon = 'Enemy.dmi'
istype = "enemy"

mob/var/istype
mob/var/attackready = 0
mob/var/choice = 0

mob
verb
attacksystem()
for(var/mob/M in oview(4))
if(M in oview(4))
if(usr.choice == 0)
if(M.istype == "enemy")
var/list/menu2 = list("Attack","Defend","Skills","Flee")
var/menu = input(usr,"Menu") in menu2
switch(menu)
if("Attack")
usr.attackready +=1
usr.choice = 1
M.checkattack()
else
return
else
M.checkattack()
else
usr<<"Not far with enemy"
mob/var/ready =0




mob/proc/checkattack()
if(usr.choice == 1)
if(usr.attackready < 4)
usr <<"you began preparing attack"
usr.attackready+=1
spawn(10)
usr.checkattack()
else
if(usr.attackready >= 4)
if(usr.ready == 0)
usr.ready = 1
usr<<"your attack is ready"
spawn(1)
usr<<"check"// just a test
usr.checkattack()
else
usr<<"check"// just a test
spawn(5)
usr.checkattack()
for(src in get_step(usr,usr.dir))
usr.choice = 0
usr.ready = 0
usr.attackready = 0
usr<<"you attack [src]"
spawn(20)
usr.attacksystem()

else
usr.attacksystem()
else
usr.checkattack()

(not sure if i should post here)

somehow it "check" part actually works for one or two, then after the 3rd time the battle test checks, it crashed my dream seeker.

Im hoping for a newer code better than this one though, I'm just testing myself if i could try make one.
In response to OneSe7en (#2)
Well, first of all, you're using spawn where it should be sleep
Second, you're looping in the checkattack() proc by re-calling the proc at the end of "something", you should look op the while() loop in the DM reference (hit F1 in dream maker)
Third, you're using usr in a proc, which is rather unreliable; restructure your checkattack() proc as a global proc and define a mob/attacker argument in the brackets like so:
checkattack(var/mob/attacker)


You should then call your checkattack proc in the attacksystem() verb like this:
checkattack(usr)


And inside your checkattack() proc, replace all of 'usr' with 'attacker'

Also, you may want to make the vars 'attackready', 'choice' and 'ready' tmp vars (var/tmp/some_temp_var), because you don't want those variables to be saved.

Also, you don't need to set an 'istype' var, you can simply use the built-in istype() proc like so:
if(istype(M, /mob/Enemy))


Also, most people will probably give you the advice to rewrite the whole thing because you are using a very unstable loop structure
In response to Nielz (#3)
thanks for the help (: but if i make it available for pvp, should i just change it like this?

if(istype(M, /mob/Enemy) || istype(M, /mob/Player))


I'm not sure how while() really works though, not really understand from the reference and also the tmp vars.

Then once like after i made the "attack" choice, my character would ready its attack and then a loops is made which will check that if the character is near the enemy or not, if it's far, it will remain active attack but if its near the enemy it will attack making the attack inactive again(but I do want to know how to make it the player will get close to the enemy and attack it, cause that's how it works in FFXII) and once I've done executing my attacks, how do I make it's the enemy's turn?

Also lastly, I want only either a certain person or his/her party only available to attack that enemy unless the user granted other people to join in fighting by requesting if the user needs a hand on the battle.

Sorry if I ask too much (:
In response to OneSe7en (#4)
"mob/var/some_var" - this var will be automatically included in a savefile when you write the mob to the savefile;

"mob/var/tmp/some_var" - this var will NOT be automatically included in a savefile when you write the mob to the savefile

When to use var/tmp/ and not just var/? Do you want the value of the variable to be saved for next time your player logs in? If not, use var/tmp

Example of when to use var/tmp:
Say you have a variable to say if a player is in a fight. So the player is in a fight and he logs out or disconnects while he was still fighting; if the var to check if the player is fighting, was not a var/tmp variable, the player would still be marked as "fighting" next time he logs in


About your question about istype(), the answer is yes

while() works fairly simple:

Within the brackets (), you set a condition, in the same fashion as how you set a condition in an if() statement.
Everything that is indented to within the while() (the same way you indent things for an if() statement) will happen again and again, holding up the rest of your proc, for as long as the condition(s) between the brackets () of your while() loop is/are true.
In response to Nielz (#5)
Ah now I understand :) thanks for the explaination though I'm not quite fully understand with the while() just yet.

So it's similar to an if() proc so to put while into the code would be something like

while(usr.attackready < 4)
usr <<"you began preparing attack"
usr.attackready+=1
sleep(10)
usr.checkattack()


or I did it wrong :s

(: i hope my other question can be answered

Thanks in advance (:
In response to OneSe7en (#6)
It's not entirely similar to an if() statement (not proc), for example, don't try and put an else 'clause' after a while() loop, because that won't even compile :p
In response to OneSe7en (#4)
And for your question about only the first attacker being able to fight the enemy, you would need to give the (enemy) mob a (tmp) variable which you use to check who the attacker is:
mob/var/tmp/attacked_by


And when you attack that enemy, the enemy's attacked_by variable is set to the attacker's key, so when some one else tries to attack your enemy, it will stop their attack if attacker.key != enemy.attacked_by
In response to OneSe7en (#2)
OneSe7en wrote:
>           for(var/mob/M in oview(4))
> if(M in oview(4))

Where did this come from? Who is teaching you this? Aside from the usr abuse, you are checking if the mob you JUST grabbed out of a list in for() is in that same list. It's redundant and I see it all over the place now. It's driving me nuts.

Ugh, I feel like I work at the Center for Disease Control. Looking for a Patient Zero, here.
In response to Nielz (#7)
So that if the player disconnects, the attackedby will automatically becomes "" or null?

so what about the party and the usr moving to the enemy to attack? the user will move to the enemy until he attacks.

oh yeah i remade the code already.
http://www.byond.com/developer/forum/?id=727243
In response to OneSe7en (#10)
Code:
mob
Enemy
icon = 'Enemy.dmi'

mob
var
tmp
ready = 0
choice = 0
attackready = 0


proc/checkattack(var/mob/attacker)
if(usr.choice == 1)
while(attacker.attackready <4)
attacker <<" Began preparing attack"
attacker.attackready+=1
sleep(10)
checkattack(attacker)
if(attacker.attackready >=4)
if(attacker.ready == 0)
attacker.ready = 1
attacker <<"attack ready"
sleep(5)
attacker <<"check"
checkattack(attacker)
else
attacker<<"check 2"
walk_to(attacker,src,0,1)
spawn(5)
checkattack(attacker)
for(src in get_step(attacker,attacker.dir))
attacker.choice = 0
attacker.ready = 0
attacker.attackready = 0
attacker <<"you attack [src]"
sleep(20)
attacker.attack2()

mob/verb/attack2()
for(var/mob/M in oview(4))
if(usr.choice == 0)
if(istype(M, .mob/Enemy))
var/list/menu2 = list("Attack","Defend","Skills","Flee")
var/menu = input(usr,"Menu") in menu2
switch(menu)
if("Attack")
usr.attackready +=1
usr.choice = 1
checkattack(usr)
else
return


Problem description: Here's what I did, though that "attacker.attack2(attacker)" might be the problem cause it's not fully working, i tried making "attack2(attacker)" but it says

"Enemies.dm:57:error:attack2:undefined proc"

When I tried testing the code out

Began preparing attack
Began preparing attack
Began preparing attack
attack ready
check
check 2
check 2

the "check 2" only comes out twice, where it should be coming continuously until it the user finally attacks the enemy and then it would be the enemy's turn(not sure on how to do this, never experienced turn based before)

I tried moving the character to the enemy with

walk_to(attacker,src,1,1)


but the character won't even move.
In response to OneSe7en (#11)
You should not be calling procs recursively, which is to say calling a proc from within itself. It's a bad practice which leads to difficult-to-read code at best, and horrible monstrosities at worst.

Basically, I have absolutely no way of telling what you are even trying to do here, or even what actually DOES happen, because all your calls to checkattack() are making a complete and utter mess of things.

Some glaring issues you can fix besides removing those recursive calls are your usr abuse: every instance of usr should be replaced with src, including changing oview(4) to oview(src,4), as otherwise it defaults to oview(usr,4). This includes the attack2() verb because you are calling it like a proc.

Another gigantic issue is the line for(src in get_step(attacker, attacker.dir)). I assume you think this is searching for src in the turf in front of attacker, but in actuality it's just putting any mobs in front of attacker into the src variable, which is really, really bad. I assume you want an if() instead of for().

Additionally, I'm entirely unclear on what is what in checkattack(). Are attacker and src supposed to be separate? Because you are passing what is (supposed to be) src as the argument, which is profoundly silly: there's no need for an argument if you can just use src. But, it's unclear on how you were meaning to use it so I can't really say.

Frankly, the whole thing is such an utter mess that I really suggest you just scrap what you have and describe what you are intending to do in words. Someone can then help you figure out a reasonable design for it, then.
In response to OneSe7en (#11)
Well "attack2(attacker)" doesn't work because your attack2() verb doesn't work with an argument, and you shouldn't call a verb in a proc, verbs should only be called by the user

And, on second thought, like Garthor said, it probably is better to make the checkattack() proc a mob/proc again, and using src inside that proc, in stead of usr, and calling it like src.checkattack() in your attack2() verb
(how could I have overlooked that one, uurrghh... haha)

Oh and change
"if(istype(M, .mob/Enemy))"
to
"if(istype(M, /mob/Enemy))"

But yeah, best thing for you to do would, be to re-write your battle system from scratch, now is the time because it's still only a few lines of code
In response to Nielz (#13)
Okay here's how it works

Final Fantasy XII Battle System

Most of final fantasy games are turned based which their battle against the enemy is usually a random wild encounter on some plains,wastelands or certain area.

As for FF XII, the battle system is actually turned based but also a real time, which is a mixture of both which means that the monsters are located on the map and no longer random encounters and once you get near them the character will start to prepare attacking them(better if the player decided to attack on it)

As the player sets its target on that enemy, a line will appear from the player to the enemy(a line from the enemy to the user also applies). A red colored line would first appeared stating that you are making your choice on what to do on that enemy and the choices are;

Attack
Magicks/Techniques(each classes have different choices)
Mist or Limit Break(It will only appear once you obtain the skill in the skill tree&maybe it will show up once you filled some sort of limit break bar)
Item

Excluded from battle menu
Flee
(In FFXII this is not included because you need to press certain buttons which will make yourself in flee state and you will make a run for it until the enemy won't follow you anymore). If the leader/member flees, then the remaining members/guests(explained later) should follow unless they want to continue the fight on their own without their leader or some members.

Once the attack is ready, the character will close up the enemy and attacks and then you will able to go around the enemy though not that far actually. But if you chose other than attack or anything does not require close-combat, then the player will remain there casting the skills(some techniques are close-combat skills). Once you attacked, the line will turns blue again for you to make the choice but before that, the it will be the enemy's turn(not if all the players fighting that enemy haven't attack yet)

Once the fight is over, the player will revert from fighting state and so that concludes the system.

Before that, also the party is only available for 3 person only or make it 4 maximum, but the maximum of people in a battle against the same enemy is 5 where the remaining number of players would be the guest granted by the user to join in battling the enemy. So its more like this, if you have 2 members party, the remaining guests that are can join the battle would be 3.

That's how i want it to be :)

It won't be that exact as the Final Fantasy XII but just similar i guess.

Sources:
http://www.youtube.com/watch?v=RSxl1FB_DUU&feature=related
http://www.ff12sector.com/ff12_gambits.php
In response to OneSe7en (#14)
What about gambits?!
In response to Metamorphman (#15)
Ah right gambits.

Gambits
It's a system which the player will configure the behavior of the player on certain conditions for example, if the player's health is around 40% it will heal itself. It depends on the option of that gambit option(it is obtainable through treasures and bought from shops if I'm not mistaken) You can also set a player to heal another player/ally if their health is low. This also applies on attacking and casting I think. You can turn on/off the gambit system :)

http://www.youtube.com/watch?v=mRIm7LrfIWg&feature=related

As you can see next to their names are the gambit icons, represented with "G" and also next to that is the attacks/actions meter which it will prepare the player for their action choices.

http://www.youtube.com/watch?v=WrfgyQR6mLo&feature=related
http://www.youtube.com/watch?v=9ePQnhMEzTs

The first link shows the interview with the battle system designer where he talks about the system and the second, i think it shows the gambit system setups where you will configure the player's behavior during the battle.

EDIT: I described wrong about the lines indicating targets. Blue indicates the player's target while red is the enemy's

Source:
http://en.wikipedia.org/wiki/Final_Fantasy_XII
In response to OneSe7en (#16)
What I want to create is just the battle system excluding the Gambit system, I can code it though it's just I'm sure just how, like I've done before, it caused me error :S

And just like Garthor&Nielz suggested, I've describe the system and provided source for it (:
In response to OneSe7en (#17)
I've been waiting for a FFXII game on BYOND, I may be able help but I work better at thinking of ideas and stuff. I have played FFXII and almost have it 100% beat, I wanted to make a FFXII game on BYOND but it's not possible for me to do solo.