Jump to content

Photo

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


  • Please log in to reply
87 replies to this topic

#61 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 June 2015 - 08:23 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)

 

 
Of course, it does. The bell curve is entirely different, with an average of 10.5 on 3d6, and a much larger pool of permutations (216, versus 15).

 

I know nothing about what tier of education you;ve attained, but here are the basics:
 
A single value, result, from a spread of 1 to 18, has a 5.55~% chance of occurring. That means that producing a 7, out of that, is the same liklihood of a 13, each at 5.55~%. This is a strictly linear result.
 
A pool of 3d6, has 216 permutations. That produces a bell curve, where some values are predominant.

Raw Odds for 3d6

 

 
 

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.

 
You could use an array, but it wouldn't be very useful, because we don't have the ability to create/define our own data structures in ZC. You essentially write a Botch(int val) function, and use if statements to determine what happens based on the input value. The input value is Rand(1,100).

 

 

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.

 

Alignment... What's you are doing, is showing the player the results of their actions. That's all alignment means.

 

If you have story events set up based on a large variety of boolean factors, including the ethical, and moral decisions of the player, then you already use alignment, whether you display it, or not. Displaying it gives the player an idea of the impact of their decisions, at a glance.

 

P.S. Alignment as the prime factor in dialogue trees would be far easier to code than per-character/prer-NPC relationships.


Edited by ZoriaRPG, 01 June 2015 - 08:27 PM.


#62 Binx

Binx

    Formerly Lineas

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

Posted 01 June 2015 - 08:28 PM

 
Of course, it does. The bell curve is entirely different, with an average of 10.5 on 3d6, and a much larger pool of permutations (216, versus 15).

 

I know nothing about what tier of education you;ve attained, but here are the basics:
 
A single value, result, from a spread of 1 to 18, has a 5.55~% chance of occurring. That means that producing a 7, out of that, is the same liklihood of a 13, each at 5.55~%. This is a strictly linear result.
 
A pool of 3d6, has 216 permutations. That produces a bell curve, where some values are predominant.

Raw Odds for 3d6

 

 
 

 
You could use an array, but it wouldn't be very useful, because we don't have the ability to create/define our own data structures in ZC. You essentially write a Botch(int val) function, and use if statements to determine what happens based on the input value. The input value is Rand(1,100).

 

 

 

Alignment... What's you are doing, is showing the player the results of their actions. That's all alignment means.

 

If you have story events set up based on a large variety of boolean factors, including the ethical, and moral decisions of the player, then you already use alignment, whether you display it, or not. Displaying it gives the player an idea of the impact of their decisions, at a glance.

 Eh, I took up through Algebra 2, but I didn't pay much attention. I was one of those "Sleep through class, ace the test" types, so I didn't retain as much as I should have (although, I did already make the 1/18 vs 1/216 connection, on my own). Anyways that was the point of my question regarding alignment, if I keep track of the moral and ethical decisions of the player, I'll be using alignment, if I don't use alignment, I'll go for the JRPG approach, with a straightforward story that doesn't change between playthroughs. I'm just wondering if the extra effort to keep track of all of those decisions is worth it.


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


#63 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 June 2015 - 08:51 PM

Eh, I took up through Algebra 2, but I didn't pay much attention. I was one of those "Sleep through class, ace the test" types, so I didn't retain as much as I should have (although, I did already make the 1/18 vs 1/216 connection, on my own). Anyways that was the point of my question regarding alignment, if I keep track of the moral and ethical decisions of the player, I'll be using alignment, if I don't use alignment, I'll go for the JRPG approach, with a straightforward story that doesn't change between playthroughs. I'm just wondering if the extra effort to keep track of all of those decisions is worth it.

 
I'd rather have changing story, and NPCs. The old JRPG approach is dead, even there. It came from not having enough space on media to fit branching dialogue trees into games. The most common game format in Japan, the visual novel, is entirely based on dialogue trees.
 
You may also enjoy this related reading.


Edited by ZoriaRPG, 01 June 2015 - 08:56 PM.

  • Binx likes this

#64 Binx

Binx

    Formerly Lineas

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

Posted 01 June 2015 - 09:06 PM

That's a good article (well, article is the wrong word, but you get my point). Getting back to the other issue at hand, though, do you know why my Botch function isn't working? I seem to have this issue with if/else statements, a lot, but I can never remember what I keep doing wrong.


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


#65 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 01 June 2015 - 09:14 PM

What's the context for those if statements? I can't see why that would cause lag if you're calling it only once per frame.

#66 Binx

Binx

    Formerly Lineas

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

Posted 01 June 2015 - 09:22 PM

They're part of a function:

void Botch()
{     
    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);
    }
}

then I placed the function inside the item script, like so:

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;
                Botch();
            }
            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);
            Trace((BotchRoll + 1000));
        }
    }

Is it that item scripts can't handle nested if statements because they only run for a single frame? or was there something else I missed? I tried putting the if statements directly in the item script, instead

item script SwordRandomDamage 
    {
        void run(int SwMinDam, int SwMaxDam)
        {
            CritChance = (Rand(1,100) + (Game->Counter[CR_LUCK]));
            if (CritChance >= 95)
            {
                SwordDamage = ((Rand(SwMinDam, SwMaxDam) + ((Game->Counter[CR_STRENGTH] - 10) * 0.25)*2));
            }
            else if (CritChance <= ((Game->Counter[CR_LUCK]) + 1))
            {
                SwordDamage = 0;
                BotchRoll = Rand(1,100);
                    if (BotchRoll == 1)
                    {
                        Link->HP -= (SwMaxDam * 2);
                    }
                    else if ((BotchRoll >= 2) && (BotchRoll <= 5))
                    {
                        Link->HP -= SwMaxDam;
                    }
                    else if ((BotchRoll >= 6) && (BotchRoll <= 10))
                    {
                        Link->HP -= Rand((SwMinDam + 1), (SwMaxDam - 1));
                    }
                    else if ((BotchRoll >= 11) && (BotchRoll <= 20))
                    {
                        Link->HP -= SwMinDam;
                    }
                    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(SwMinDam,SwMaxDam);
                    }
                    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(SwMinDam, SwMaxDam) * 0.5);
                    }
                    else if ((BotchRoll >= 97) && (BotchRoll <= 99))
                    {
                    Damage = Rand(SwMinDam, SwMaxDam);
                    }        
                    else if (BotchRoll == 100)
                    {
                    Damage = (Rand(SwMinDam, SwMaxDam) * 2);
                    }
            }
            else if ((CritChance < 100) && (CritChance > (Game->Counter[CR_LUCK] + 1)))
            {
                SwordDamage = (Rand(SwMinDam, SwMaxDam) + ((Game->Counter[CR_STRENGTH] - 10) * 0.25));
            }
            ModItemPower(SwordPower,SwordDamage);
            Trace(SwordDamage);
            Trace(CritChance);
            Trace((BotchRoll + 1000));
        }
    } 

, but that didn't work either. So, I'm not sure if it's a limitation of item scripts, or if I missed something, because it compiles all right.


Edited by Binx, 01 June 2015 - 09:27 PM.


#67 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 01 June 2015 - 09:54 PM

Those return statements might be ending the item script prematurely if you place the if statements directly there, but they should be fine if they're confined to the function. I assume MinDam, MaxDam, BotchRoll, and Damage are all global variables?

#68 Binx

Binx

    Formerly Lineas

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

Posted 01 June 2015 - 10:04 PM

Yeah, it wouldn't have compiled, otherwise (learned that the hard way). Why would the return lines be ending the item script prematurely, it uses order of operations, right, so shouldn't the botch calculations be performed last? 

 

EDIT: Never mind. Apparently it was all working just fine, even with the functions, it was just happening so rarely I didn't see it working. I changed the CritChance roll from 1d100 to 1d20, so that should fix everything. But, now that I think of it, the break/lose item functions probably won't work well for my quest, since some items aren't really items, but spells or abilities. So, I'm gonna have to think of other things to put there. Maybe more stamina reducing functions, in the same vein as the HP reducing ones.


Edited by Binx, 01 June 2015 - 10:27 PM.


#69 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 01 June 2015 - 11:08 PM

Yeah, it wouldn't have compiled, otherwise (learned that the hard way). Why would the return lines be ending the item script prematurely, it uses order of operations, right, so shouldn't the botch calculations be performed last? 

 

EDIT: Never mind. Apparently it was all working just fine, even with the functions, it was just happening so rarely I didn't see it working. I changed the CritChance roll from 1d100 to 1d20, so that should fix everything. But, now that I think of it, the break/lose item functions probably won't work well for my quest, since some items aren't really items, but spells or abilities. So, I'm gonna have to think of other things to put there. Maybe more stamina reducing functions, in the same vein as the HP reducing ones.

 

Rekey your spells to a boolean array index, so that they can be used only if an index with a matching constant is true. That will allow you to disable them, or enable them, as if they were items. Jusgt add an evaluation statement to the spellk itself, :

 

e.g.

if ( ( conditions ) && HasSpell(FIREBALL) ){
    //cast the spell;
}
 
bool HasSpell(int spell) {
     return HasSpells[spell];
}
 
bool HasSpells[256];
 
const int FIREBALL = 0;

That's essentially what I do to handle this sort of thing, and it also allows you to disable spells when using them is irrational (such as fire magic, underwater; or casting waster magic in a volcano caldera).


Edited by ZoriaRPG, 01 June 2015 - 11:08 PM.


#70 Binx

Binx

    Formerly Lineas

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

Posted 01 June 2015 - 11:11 PM

Well, yeah, I guess I could do that, but it makes a good portion of the botch table useless to do so. Stamina reduction works just fine, I think. Given the importance of food in this quest, I think it's a good idea (I finally figured out what stamina's going to do. Rather than kill you automatically if it's empty, you'll lose HP every x frames while the meter's empty. This should give people enough time to notice that their life is draining and make sure they eat before they die, and if they have no food, they might be able to get to a place where they can purchase some, provided they can keep their health up long enough to get there) Besides, I don't want to think about how much more work it would be to add durability ratings to all the items.

 

EDIT: I also reduced the botch table down to Rand(1,20), because it was hardly ever doing anything, before.


Edited by Binx, 02 June 2015 - 01:35 AM.


#71 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 02 June 2015 - 02:27 AM

Well, yeah, I guess I could do that, but it makes a good portion of the botch table useless to do so. Stamina reduction works just fine, I think. Given the importance of food in this quest, I think it's a good idea (I finally figured out what stamina's going to do. Rather than kill you automatically if it's empty, you'll lose HP every x frames while the meter's empty. This should give people enough time to notice that their life is draining and make sure they eat before they die, and if they have no food, they might be able to get to a place where they can purchase some, provided they can keep their health up long enough to get there) Besides, I don't want to think about how much more work it would be to add durability ratings to all the items.
 
EDIT: I also reduced the botch table down to Rand(1,20), because it was hardly ever doing anything, before.

Item->Misc[] would do for durability, and damage. That mate, gives you the power of automation, and should keep the vital stats for each item, isolated without any tomfoolery.

You can run a constant for loop to disable broken items, or reduce the power of damaged items.

I suggest
 ( ( Rand(1, 8) + Rand(1,6) + Rand(1, 8) ) - 2 )
for a curve. That will give you a range of 1-20, without an exact percentage of each number. It will average at 12.5, with a sweet spot of 10-15 if the RNG is high, or 9-13 if the RNG is low, giving you some room to set up averages.

If the d100 table was producing 'nothing' too often, then something is broken with the RNG. It had a 75% chance of producing an effect.

Edited by ZoriaRPG, 02 June 2015 - 02:36 AM.


#72 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 02 June 2015 - 03:08 AM

Unfortunately that wouldn't work. item->Misc[] applies to items spawned on the screen, not items in Link's inventory.

#73 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 02 June 2015 - 03:13 AM

Unfortunately that wouldn't work. item->Misc[] applies to items spawned on the screen, not items in Link's inventory.

Well, that's not made clear by zscript.txt, and puts a spanner in my plans. I suppose I'll just add an array for that sort of thing, but Item->Misc would have been nice.

I suppose it makes sense though, as otherwise, NPC->Misc would be static between enemies of the same ID.

Lejes, Binx, help me think of some good uses for temporary Item->Misc so that I can salvage some of the functions, and routines that I have for it, whilst I adapt everything to use a 4096 sized array.

Here's the code that I made, with changes to reflect this problem:



That's part of the entirely untested (not even compile tested) zlib files for RPG.zh (RPG_Items_Misc.zlib).
This may be a useful framework, as I already modified it into an array; but the lost item functions are as yet, incomplete.

P.S. I'm using functions to splot the float value high/low, so that all the fields still fit into a 16-index array, in case anyone has good ideas for using Item->Misc[], so that it's easy to shift a full set of sixteen values from the array, to the Misc indices.

Edited by ZoriaRPG, 02 June 2015 - 04:31 AM.


#74 Lejes

Lejes

    Seeker of Runes

  • Members
  • Location:Flying High Above Monsteropolis

Posted 02 June 2015 - 04:10 AM

The only thing I've used it for is to give an item more complex movement and spawn timers. I had it set up so the items moved in a sine wave, and more wouldn't spawn in unless the previous copy had a Misc value set to something. I couldn't just check for other copies of the item, because I was removing old ones by setting the IP_TIMEOUT flag, which makes it disappear 512 frames later. I'm not sure if there is another way to get rid of items other than collecting them or calling Screen->ClearSprites(), but that will eliminate all items on screen.

#75 Timelord

Timelord

    The Timelord

  • Banned
  • Location:Prydon Academy

Posted 02 June 2015 - 04:35 AM

The only thing I've used it for is to give an item more complex movement and spawn timers. I had it set up so the items moved in a sine wave, and more wouldn't spawn in unless the previous copy had a Misc value set to something. I couldn't just check for other copies of the item, because I was removing old ones by setting the IP_TIMEOUT flag, which makes it disappear 512 frames later. I'm not sure if there is another way to get rid of items other than collecting them or calling Screen->ClearSprites(), but that will eliminate all items on screen.


//Removes Item 'i' from the screen
void Remove(item i){
	if(!i->isValid()) return;
	i->X = 32768;
}
...in std_functions.zh, but it just moves the position. I don't know if IsValid() will return when an item is that far out of range, although I suspect that the pointer remains valid.

You can however, use this in conjunction with a check for items within a specified range, and create more when none are in the area.
 
 //Utility
//v0.2

void CopyArray(int src, int dest){
	for (int i = 0; i < SizeOfArray(src); i++){
		src[i] = dest[i];
	}
}
	
void CopyArrayB(int size, int src, int dest){ //SizeOfArray() does not work on Boolean arrays, which is why it's prudent to have a bboolean array and an int or float array in pairs with identical index sizes.
	for (int i = 0; i < size; i++){
		src[i] = dest[i];
	}
}


void MirrorCounter(int main, int mirror){
	Game->Counter[mirror] = Game->Counter[main];
}

void MirrorMCounter(int main, int mirror){
	Game->MCounter[mirror] = Game->MCounter[main];
}

void MirrorDCounter(int main, int mirror){
	Game->DCounter[mirror] = Game->DCounter[main];
}

 bool isOnScreen(item i){
	if( i->isValid() && i->X != 32768 ) {
		return true;
	}
	return false;
}

 bool isOnScreen(ffc f){
	if( f->Data > 0 && f->X != 32768 ) {
		return true;
	}
	return false;
}

 bool isOnScreen(npc n){
	if( n->isValid() && n->X != 32768 ) {
		return true;
	}
	return false;
}

 bool isOnScreen(eweapon e){
	if( e->isValid() && e->X != 32768 ) {
		return true;
	}
	return false;
}

bool isOnScreen(lweapon l){
	if( l->isValid() && l->X != 32768 ) {
		return true;
	}
	return false;
}
That would probably suffice.

Edited by ZoriaRPG, 02 June 2015 - 04:46 AM.



0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users