Jump to content

Photo

Please help me with drawing scripted meters, assigning extra buttons &


  • Please log in to reply
87 replies to this topic

#46 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 27 May 2015 - 11:52 AM

Honestly, crits shouldn't be too hard to implement, since random damage is already a thing. You just add an extra variable "CritChance" which is equal to (Rand(1,100) + Game->Counter[CR_LUCK]) then write an if statement: if (CritChance >= 100), itemdata->Power = Damage * 2 (where Damage is the result of the random damage roll); else if (CritChance == Game->Counter[CR_LUCK] +1), itemdata->Power = 0 (gotta figure out how to stop botches from stunning, though, without removing stunning from other power 0 weapons); else, itemdata->Power = Damage. For me, the bigger problems are A)Setting enemies up to deal random damage, as well (think I need an array, for that, dunno how to make it) and B) finding a workaround to the "damage dealt is always an even number" bullshit. I'm thinking of just doubling the enemy HP, then halving their actual HP and damage dealt wherever its displayed.... Or I guess I could just activate "1/2 damage" for every weapon type, and let the engine do the rest. Dunno if the second thing will work, though.

 

EDIT: Yep, it worked. Now to add the crits and extra stat.

 

FURTHER EDIT: In case you're interested, this is how I implemented it with my swords, tested and functional:

float SwordDamage;
const int SwordPower = 121; //set this to the item id of a whimsical ring-class item with
//a power of 0 and a chance of 1 in 1
const int CR_COPPER = 7;
const int CR_SILVER = 8;
const int CR_BREAD = 9;
const int CR_MEAT = 10;
const int CR_ALE = 11;
const int CR_HP = 12;
const int CR_MAXHP = 13;
const int CR_SP = 14;
const int CR_MAXSP = 15;
const int CR_MP = 16;
const int CR_MAXMP = 17;
const int CR_XP = 18;
const int CR_MAXXP = 19;
const int CR_LV = 20;
const int CR_STRENGTH = 21;
const int CR_INTELLECT = 22;
const int CR_DEXTERITY = 23;
const int CR_CHARISMA = 24;
const int CR_MAXCOIN = 25;
const int CR_LUCK = 26;
int CritChance;  

//Relatively easy edits could be used to make this work for any weapon type, rather than only swords
//I'll post that code up when I finish it.



item script SwordRandomDamage 
    {
        void run(int SwMinDam, int SwMaxDam)
        {
            CritChance = (Rand(1,100) + Game->Counter[CR_LUCK]);
            if (CritChance >= 100)
            {
                SwordDamage = ((Rand(SwMinDam, SwMaxDam) + ((Game->Counter[CR_STRENGTH] - 10) * 0.25)*2));
            }
            else if (CritChance == (Game->Counter[CR_LUCK] + 1))
            {
                SwordDamage = 0;
            }
            else if ((CritChance < 100) && (CritChance > (Game->Counter[CR_LUCK] + 1)))
            {
                SwordDamage = (Rand(SwMinDam, SwMaxDam) + ((Game->Counter[CR_STRENGTH] - 10) * 0.25));
            }
            itemdata id = Game->LoadItemData(SwordPower);
            id->Power = SwordDamage;

            Trace(SwordDamage);
            Trace(CritChance);
        }
    }

Edited by Binx, 27 May 2015 - 01:24 PM.


#47 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 27 May 2015 - 01:46 PM

And the versions for non-sword weapons (so much easier to set up, lol)

float Damage;

item script RangedRandomDamage 
    {
        void run(int MinDam, int MaxDam)
        {
            CritChance = (Rand(1,100) + Game->Counter[CR_LUCK]);
            if (CritChance >= 100)
            {
                Damage = ((Rand(MinDam, MaxDam) + ((Game->Counter[CR_DEXTERITY] - 10) * 0.25)*2));
            }
            else if (CritChance == (Game->Counter[CR_LUCK] + 1))
            {
                Damage = 0;
            }
            else if ((CritChance < 100) && (CritChance > (Game->Counter[CR_LUCK] + 1)))
            {
                Damage = (Rand(MinDam, MaxDam) + ((Game->Counter[CR_DEXTERITY] - 10) * 0.25));
            }
            this->Power = Damage;
            Trace(Damage);
            Trace(CritChance);
        }
    }
    
item script MeleeRandomDamage 
    {
        void run(int MinDam, int MaxDam)
        {
            CritChance = (Rand(1,100) + Game->Counter[CR_LUCK]);
            if (CritChance >= 100)
            {
                Damage = ((Rand(MinDam, MaxDam) + ((Game->Counter[CR_STRENGTH] - 10) * 0.25)*2));
            }
            else if (CritChance == (Game->Counter[CR_LUCK] + 1))
            {
                Damage = 0;
            }
            else if ((CritChance < 100) && (CritChance > (Game->Counter[CR_LUCK] + 1)))
            {
                Damage = (Rand(MinDam, MaxDam) + ((Game->Counter[CR_STRENGTH] - 10) * 0.25));
            }
            this->Power = Damage;
            Trace(Damage);
            Trace(CritChance);
        }
    }
    
item script MagicRandomDamage 
    {
        void run(int MinDam, int MaxDam)
        {
            CritChance = (Rand(1,100) + Game->Counter[CR_LUCK]);
            if (CritChance >= 100)
            {
                Damage = ((Rand(MinDam, MaxDam) + ((Game->Counter[CR_INTELLECT] - 10) * 0.25)*2));
            }
            else if (CritChance == (Game->Counter[CR_LUCK] + 1))
            {
                Damage = 0;
            }
            else if ((CritChance < 100) && (CritChance > (Game->Counter[CR_LUCK] + 1)))
            {
                Damage = (Rand(MinDam, MaxDam) + ((Game->Counter[CR_INTELLECT] - 10) * 0.25));
            }
            this->Power = Damage;
            Trace(Damage);
            Trace(CritChance);
        }
    }

item script PerformanceRandomDamage 
    {
        void run(int MinDam, int MaxDam)
        {
            CritChance = (Rand(1,100) + Game->Counter[CR_LUCK]);
            if (CritChance >= 100)
            {
                Damage = ((Rand(MinDam, MaxDam) + ((Game->Counter[CR_CHARISMA] - 10) * 0.25)*2));
            }
            else if (CritChance == (Game->Counter[CR_LUCK] + 1))
            {
                Damage = 0;
            }
            else if ((CritChance < 100) && (CritChance > (Game->Counter[CR_LUCK] + 1)))
            {
                Damage = (Rand(MinDam, MaxDam) + ((Game->Counter[CR_CHARISMA] - 10) * 0.25));
            }
            this->Power = Damage;
            Trace(Damage);
            Trace(CritChance);
        }
    }  

Edited by Binx, 27 May 2015 - 01:51 PM.


#48 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 05:20 AM

My botches (critical failures, a role of 1 out of a random roll between 1 and 100) aren't working well. I mean, it's only about 1/100 chance to botch, but man, oh man, do botches hurt (they can kill you in 2-5 hits at the start of the quest, depending on your initial HP total and the weapon you use, granted that's a lot of sword swinging, and crit fails very rarely happen, but I worry it will unbalance the game too much). A botch does the weapon's base damage (without modifiers) to you, so if you botch on a longsword (1-6) you take somewhere between 1 and 6 damage, which is a lot of damage considering the MAX you can start with is 18, and you can technically start as low as 3. I guess I could just count on the players being at least a few levels up before they start getting real weapons, but it just seems really unforgiving, but other methods (such as making it only do 2 damage) seemed too weak, especially at higher levels.. Any ideas?



#49 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 June 2015 - 01:26 PM

My botches (critical failures, a role of 1 out of a random roll between 1 and 100) aren't working well. I mean, it's only about 1/100 chance to botch, but man, oh man, do botches hurt (they can kill you in 2-5 hits at the start of the quest, depending on your initial HP total and the weapon you use, granted that's a lot of sword swinging, and crit fails very rarely happen, but I worry it will unbalance the game too much). A botch does the weapon's base damage (without modifiers) to you, so if you botch on a longsword (1-6) you take somewhere between 1 and 6 damage, which is a lot of damage considering the MAX you can start with is 18, and you can technically start as low as 3. I guess I could just count on the players being at least a few levels up before they start getting real weapons, but it just seems really unforgiving, but other methods (such as making it only do 2 damage) seemed too weak, especially at higher levels.. Any ideas?

 
Botch/fumble... Perhaps put in a separate routine with a table of things to do, if the result of AttackRoll is '1':
 
Effect of Botch Table

01 	: Self-critical hit,
02-05 	: Major injury to self,
06-10 	: Moderate injury to self,
11-20 	: Minor injury to self,
21-30 	: Drunk movement for duration (unbalanced...been working on a better function for that),
31-40 	: Nothing Happens 10% (padding for balance),
41-50 	: -1d4 Str/Stamina for X-minutes (exhausted),
51-65 	: Nothing happens 15% (total 25% in two number ranges).
66-80 	: Lose item (remove from inventory, and place on screen within 5 tiles of player (you will also 
	  need to store a value in Screen->D when this happens, so that leaving the screen, and returning puts 
	  the item somewhere on the screen),
81-90 	: Break item (will require a way to fix it for unique items, or any items, or replace non-unique items,
91-97 	: Hits enemy for reduced (halved) damage,
98-99 	: Hits enemy for normal damage *on enemy* (recursive recovery),
100 	: Hits enemy for accidental crit *on enemy* (recursive luck). 

For P&P games, I generally set up the best things on a d100 table at the lowest numbers (a low percent change of someting happening), but here, it doesn't much matter.

 

You should also Trace the value of the AttackRoll, and any other important RNG in tables, and see if any values are occurring more often than they should (imperfect RNG) and adjust out, or around those values.

 

I've noticed that some RNG routines will get stuck on low ranges, for a while, then get stuck on medium, or high ranges, for a while. One thing I've done in the past, is to flush RNG routines, by performing a Rand(1,1) 50 times before producing the next value to be used. That can help randomise operations that are stuck in a low/medium/high number range.

 

Shifting from d20 to d100 on the attack roll itself could also give you a level of fineness, for detecting if these events occur more than they should, and adjust crits down from 5% ('1' on d20) to 3%, or something suitable.


Edited by ZoriaRPG, 01 June 2015 - 01:34 PM.


#50 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 02:04 PM

Actually, I have been tracing those values, and the RNG seems to be working all right (although it turns out that

((Rand(1,6)) + (Rand(1,6)) + (Rand(1,6))) 

consistently returns a slightly higher roll than 

Rand (3,18) 

, my guess is that it somehow involves probability and stuff that I didn't pay attention to when we talked about it in math class, so, whatever)

I like your idea of a botch table. Is it just a series of nested if statements, or is there some easier way to do it with an array? Cuz, I can definitely do the if/else statement way, and the botch table idea seems really good.


Edited by Binx, 01 June 2015 - 02:05 PM.


#51 Avaro

Avaro

    >w<

  • Members

Posted 01 June 2015 - 02:08 PM

I'm not a fan of randomness generally. I prefer the idea of collecting stacks by doing comboes or something in that direction.

Not saying that what you are doing is wrong though. I appreciate how you do something new and different from other quests! And of course there's that RPG flavour too :)



#52 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 02:19 PM

I'm not a fan of randomness generally. I prefer the idea of collecting stacks by doing comboes or something in that direction.

Not saying that what you are doing is wrong though. I appreciate how you do something new and different from other quests! And of course there's that RPG flavour too :)

Well, that's the main thing, this quest isn't an Action/Adventure game, it's an Action/RPG, so things like random damage, critical hits and botches are added to give the quest a little more flavor, and because I've never been a fan of "This enemy always dies in x hits" mentality to gameplay, it always reminds me of that god-awful LoZ cartoon where "Link" (in quotes, because that sarcastic jackass of a fantasy-based Wheeler clone is NOT the Hero of Hyrule) tells "Ganon" (quoted for the same reason) "Two zaps, Ganon, one more and you're history!" like he'd read the goddamned manual or something. Not that it's wrong, I just prefer the RPG-style elements.



#53 Avaro

Avaro

    >w<

  • Members

Posted 01 June 2015 - 03:22 PM

Well, that's the main thing, this quest isn't an Action/Adventure game, it's an Action/RPG, so things like random damage, critical hits and botches are added to give the quest a little more flavor, and because I've never been a fan of "This enemy always dies in x hits" mentality to gameplay, it always reminds me of that god-awful LoZ cartoon where "Link" (in quotes, because that sarcastic jackass of a fantasy-based Wheeler clone is NOT the Hero of Hyrule) tells "Ganon" (quoted for the same reason) "Two zaps, Ganon, one more and you're history!" like he'd read the goddamned manual or something. Not that it's wrong, I just prefer the RPG-style elements.

 
I totally see where you are coming from. It's fine and I'm sorry for going a bit off topic about this but I like talking about these things.

Edited by Avataro, 01 June 2015 - 03:29 PM.


#54 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 03:33 PM

Eh, doesn't bug me, none. I love getting feedback about ideas and how I'm planning to implement them.



#55 Avaro

Avaro

    >w<

  • Members

Posted 01 June 2015 - 03:37 PM

I've also been thinking about your question about 1/6 + 1/6 + 1/6 vs 3/18. You are right about it. Getting a 3 as a result has a very very low chance with the first method, unlike getting a 10 for example, because there are a lot more possible combinations.
  • Binx likes this

#56 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 03:54 PM

Yeah, I figured it was something like that, rolling a 3 is only 1/18 with a 3-18 range, but 3d6 is a chance of 1/216, so the odds towards the middle are much larger. It does make it less likely to roll a high number, as well, but them's the breaks.

 

I've also been wondering, is it possible, via scripting to reassign the function of the "Start" button (so that it doesn't bring up the active subscreen, or pause scripts, but can still be used  for something else, like a scripted menu or subscreen)? I've been thinking that I'd like to use the "Start" and "Map" buttons, rather than L/R for menus and the maps, and reassign L/R to cycle between a few "Skill Slots" that I'd place on the passive subscreen (I got the idea from that LoZ hack that let you choose three items and switch between them with "select") I figure that part would be actually easy, since I'm planning to use dummy items and a blank inventory to assign weapons (so, technically, the only equipment items the player "has" are the ones currently equipped to slots, so the base L/R functions would actually work, there. As an example, say you own a boomerang, bombs, DIn's FIre the whistle and a potion, while they're in your "Items" bag, they're all dummy items, and Link->Item[i] is set to false for the real item, When the dummy item is equipped, it sets Link->Item[i] to true for the real item, so, the only ones actually able to be cycled through with L/R are the ones equipped to slots, and you could set 3 of them)



#57 Avaro

Avaro

    >w<

  • Members

Posted 01 June 2015 - 04:09 PM

Yes, it's possible:

global script Active{
    void run(){
        while(true){
            Link->PressStart = false;
            Link->InputStart = false;
            Waitframe();
        }
    }
}

ffc script MainMenuScript{
    void run(){
        while(true){
            if ( Link->PressStart ) {
                //menu
            }
            Waitframe();
        }
    }
}

This definetly works for me, but I'm not sure right now if it's required to have the main menu in an FFC script or if it can be in the global script too. I didn't try xD



#58 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 04:14 PM

Oh, cool, that makes things much simpler. Especially because it allows me to use the hidden active subscreen I'd planned on (Honestly, I wasn't exactly sure how else I'd get the items to work, properly, since it doesn't seem to allow b button items unless  they're actually on the active subscreen). I'd assume it could be part of the global, since it only uses the one waitframe, so I don't see any reason it wouldn't work as a global. In fact, you could probably just make it a function and call it inside the global script.


Edited by Binx, 01 June 2015 - 04:17 PM.


#59 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 05:00 PM

On a different note, is alignment a worthwhile mechanic to add? If I do add it, it will be used to affect relationships with various NPCs and your reputation in the world at large especially in regards to a romance subplot, but on the other hand, branched conversational paths are incredibly difficult to add. And I'm not sure if the added story aspects would make enough of a difference to be worthwhile.


Edited by Binx, 01 June 2015 - 05:01 PM.


#60 Binx

Binx

    Formerly Lineas

  • Members
  • Real Name:Brian
  • Location:Lancaster, CA

Posted 01 June 2015 - 08:10 PM

SO, I tried to put a table together like this:

 
{     
    BotchRoll = Rand(1,100);
    if (BotchRoll == 1)
    {
        Link->HP -= (MaxDam * 2);
    }
    else if ((BotchRoll >= 2) && (BotchRoll <= 5))
    {
        Link->HP -= MaxDam;
    }
    else if ((BotchRoll >= 6) && (BotchRoll <= 10))
    {
        Link->HP -= Rand((MinDam + 1), (MaxDam - 1));
    }
    else if ((BotchRoll >= 11) && (BotchRoll <= 20))
    {
        Link->HP -= MinDam;
    }
    else if ((BotchRoll >= 21) && (BotchRoll <= 30)) 
    {
        Link->Drunk = 300;
    }
    else if ((BotchRoll >= 31) && (BotchRoll <= 40))
    {
        return;
    }
    else if ((BotchRoll >= 41) && (BotchRoll <= 50))
    {
        Game->Counter[CR_SP] -= Rand(MinDam,MaxDam);
    }
    else if ((BotchRoll >= 51) && (BotchRoll <= 65))
    {
        return;
    }
    else if ((BotchRoll >= 66) && (BotchRoll <= 80))
    {
        return; //to be replaced with Lose item function, just as soon as I write it
    }
    else if ((BotchRoll >= 81) && (BotchRoll <= 90))
    {
        return; //to be replaced with "break item" function
    }
    else if ((BotchRoll >= 91) && (BotchRoll <= 96))
    {
        Damage = (Rand(MinDam, MaxDam) * 0.5);
    }
    else if ((BotchRoll >= 97) && (BotchRoll <= 99))
    {
        Damage = Rand(MinDam, MaxDam);
    }
    else if (BotchRoll == 100)
    {
        Damage = (Rand(MinDam, MaxDam) * 2);
    }
}

 but there's two problems: First, it seems to cause lag (and freezing, occasionally), and secondly, I don't think it's working. I traced the  value of BotchRoll, but none of the effects were happening, regardless of what was returned. For example, when it rolled an 18 on the botch (represented by a trace in allegro.log as 1018.0000), it SHOULD have subtracted 1HP from Link, but instead did nothing, at another point it rolled 43, but didn't remove any SP from the counter..


Edited by Binx, 01 June 2015 - 08:30 PM.



1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users