Author Topic: drug table madness. Drugs.fos is broken. [old TLA SDK.]  (Read 3549 times)

drug table madness. Drugs.fos is broken. [old TLA SDK.]
« on: August 28, 2017, 08:40:02 pm »
Hello, I was trying new drugs, adding or editing the existing ones and everything got messed up. Obviously. That was expected.
But the point is, I wanted to know where and why. So I deleted the full list of drug effects and left the stimpak. Tested. Worked just fine. Then added  the Radaway. Tested. BAD. All wrong. It caused Jet effect. I checked every ID and jet ID is 17. Stimpak is 0 and Radaway is 1. So, if I'm using Radaway, why the hell it uses Jet while it's not even listed to have an effect!!?
« Last Edit: August 28, 2017, 08:41:58 pm by Grey »

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #1 on: August 28, 2017, 08:49:17 pm »
Which revision sdk? Post the drug.fos and drug_data.fos if they exist.

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #2 on: August 28, 2017, 09:04:25 pm »
I have absolutely no idea which revision is this. Is a very stable version from 2011/2012 and it's TLA SDK. There is no drug_data.fos

Code: [Select]
// Author: cvet
// Original Fallout2 system
#include "_macros.fos"
#include "_msgstr.fos"

import void AffectRadiation( Critter& cr, int value ) from "radiation";
import void AffectPoison( Critter& cr, int value ) from "poison";
import void AffectHambre(Critter& cr, int value) from "Hambre";

// Chem Reliant
// benefit: Faster recovery from chem side effects
// penalty: Doubles chance for addiction
// Chem Resistant
// benefit: 50% less addiction chance
// penalty: 50% less duration for Chem effects
#define DRUG_EFFECT_DIV2_WITHDRAWAL    ( 1 )
#define DRUG_EFFECT_MUL2_ADDICTION     ( 2 )
#define DRUG_EFFECT_DIV2_ADDICTION     ( 4 )
#define DRUG_EFFECT_DIV2_DURATION      ( 8 )
#define RATE_TO_STAGE                  # (rate)          ( ( rate ) & 0xFFFFFF )
#define RATE_TO_FLAGS                  # (rate)          ( ( rate ) >> 24 )
#define FORM_RATE                      # ( stage, flags )( ( ( ( flags ) & 0xFF ) << 24 ) | ( ( stage ) & 0xFFFFFF ) )

#define FOOD_DRUG                      # (_pid) ((_pid) == PID_WATER_CLEAN)


const int[] DrugsIdentifiers =
{
    PID_STIMPAK, PID_RADAWAY, PID_ANTIDOTE, PID_RAD_X, PID_SUPER_STIMPAK, PID_JET_ANTIDOTE, PID_HEALING_POWDER, PID_HYPO,
    PID_NUKA_COLA, PID_BEER, PID_BOOZE, PID_GAMMA_GULP_BEER, PID_ROENTGEN_RUM, PID_ROT_GUT, PID_MENTATS, PID_BUFFOUT, PID_PSYCHO, PID_JET,
    PID_MUTATED_FRUIT, PID_IGUANA_ON_A_STICK, PID_MEAT_ON_A_STICK, PID_COOKIE, PID_HYPO_POISON, PID_MUTATED_TOE, PID_KITTY_SEX_DRUG_AGILITY,
    PID_KITTY_SEX_DRUG_INTELLIGENCE, PID_KITTY_SEX_DRUG_STRENGTH, PID_MONUMENT_CHUNCK, PID_BOX_OF_DOUGHNUTS, PID_WATER_PURE, PID_WATER_CLEAN,
PID_WATER_DIRTY, PID_WATER_RAD, PID_BRAHMIN_MEAT, PID_GECKO_MEAT, PID_BRAHMIN_STEAK, PID_GECKO_STEAK, PID_BEANS, PID_RAVIOLI, PID_CANNEDBEEF
};

const int[] DrugEffects =
{
// PID_STIMPAK
    -1,      0,             0,      0,          0,     0,
    -2,        10,      0,      0,          0,     0,
    ST_CURRENT_HP,        40,      0,      0,          0,     0,
    -1,         0,      0,      0,          0,     0,
    -1,         0,      0,      0,          0,     0,
// PID_RADAWAY
    ADDICTION_RADAWAY,     10,           120,    120,      14160, 10080,
    ST_RADIATION_LEVEL,       -25,    -50,    -75,          0,     0,
    ST_RADIATION_RESISTANCE,         0,      0,      0,        -20,    20,
    -1,         0,      0,      0,          0,     0,
    -1,         0,      0,      0,          0,     0,
};

// Table offsets
#define TABLE_DRUG_ADDICT    ( 0 )
#define TABLE_DRUG_PROC      ( 1 )
#define TABLE_DURATION       # (stage)      ( 2 + ( stage ) )
#define TABLE_STAT           # (stat)           ( 6 + ( stat ) * 6 )
#define TABLE_AMOUNT         # ( stat, stage )( 7 + ( stage ) + ( stat ) * 6 )


void UseDrug(Critter& cr, Item& drug)   // Export
{
    uint pid = drug.GetProtoId();
    SetDrug(cr, pid);
    _SubItem(drug, 1);
    if(pid == PID_STIMPAK || pid == PID_SUPER_STIMPAK)
    {
        cr.AddItem(PID_HYPODERMIC_NEEDLE, 1);
cr.Say(SAY_EMOTE_ON_HEAD,"injects something");
    }
if(pid == PID_WATER_PURE || pid == PID_WATER_CLEAN || pid == PID_WATER_DIRTY || pid == PID_WATER_RAD)
    {
        cr.PlaySound( "gulping.ogg", true );
        cr.AddItem(PID_EMPTY_WB, 1);
cr.Say(SAY_EMOTE_ON_HEAD,"drinks some water");
    }
if(pid == PID_BRAHMIN_MEAT || pid == PID_GECKO_MEAT || pid == PID_BRAHMIN_STEAK || pid == PID_GECKO_STEAK || pid == PID_BEANS || pid == PID_RAVIOLI || pid == PID_CANNEDBEEF || pid == PID_MUTATED_FRUIT || pid == PID_IGUANA_ON_A_STICK || pid == PID_MEAT_ON_A_STICK || pid == PID_COOKIE || pid == PID_MEAT_JERKY)
    {
        cr.Say(SAY_EMOTE_ON_HEAD,"eats something");
    }
if(pid == PID_NUKA_COLA)
    {
        cr.PlaySound( "gulping.ogg", true );
        cr.AddItem(PID_BOTTLE_GLASS, 1);
cr.Say(SAY_EMOTE_ON_HEAD,"drinks NukaCola");
    }
if(pid == PID_BEER || pid == PID_BOOZE || pid == PID_GAMMA_GULP_BEER || pid == PID_ROENTGEN_RUM || pid == PID_ROT_GUT)
    {
    cr.PlaySound( "gulping.ogg", true );
        cr.AddItem(PID_BOTTLE_GLASS, 1);
cr.Say(SAY_EMOTE_ON_HEAD,"drinks something");
}
   
}

void UseDrugOn( Critter& cr, Critter& onCr, Item& drug ) // Export
{
    if( onCr.IsDead() )
    {
        cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_SKILL_NORESSURECT );
        return;
    }

    bool isStimpak = ( drug.GetProtoId() == PID_STIMPAK || drug.GetProtoId() == PID_SUPER_STIMPAK );
    if( isStimpak || onCr.IsKnockout() /* || Random(0,cr.Skill[SK_FIRST_AID])>onCr.Stat[ST_PERCEPTION]*20*/ )
    {
        onCr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_USE_ON_SUCC );
        SetDrug( onCr, drug.GetProtoId() );
    }
    else
    {
        onCr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_USE_ON_FAIL );
    }

    _SubItem( drug, 1 );
    if( not isStimpak )
        cr.TimeoutBase[ TO_SK_FIRST_AID ] = FIRST_AID_TIMEOUT( cr );
}

void DropDrugEffects( Critter& cr ) // Export
{
    // Clear effects of all active drugs
    // Drop
    // int[] identifiers;
    // uint[] rates;
    // uint count=cr.GetTimeEvents(DrugsIdentifiers,identifiers,null,null,rates);
    // for(uint i=0;i<count;i++) DropDrug(cr,identifiers[i],rates[i]);
    // Броня убирается в инвентарь, чтобы избежать эффекта снятия бонусов от armor perk
    Item@[] items;
    cr.GetItems( SLOT_ARMOR, items );
    cr.GetItems( SLOT_HAND1, items );
    cr.GetItems( SLOT_HAND2, items );
    for( uint i = 0, l = items.length(); i < l; i++ )
        _CritMoveItem( cr, items[ i ], SLOT_INV );

    for( uint i = STAT_EXT_BEGIN; i <= STAT_EXT_END; i++ )
        cr.StatBase[ i ] = 0;
    // Erase all events
    cr.EraseTimeEvents( DrugsIdentifiers );
    // Unset addictions perks
    for( uint i = ADDICTION_BEGIN; i <= ADDICTION_END; i++ )
        cr.AddictionBase[ i ] = 0;
    // Обратно возвращаем броню
    for( uint i = 0, l = items.length(); i < l; i++ )
    {
        Item@ item = items[ i ];
        if( valid( item ) && item.GetType() == ITEM_TYPE_ARMOR )
        {
            _CritMoveItem( cr, item, SLOT_ARMOR );
            break;             // может быть более 1 брони в руках
        }
    }
}

void SetDrug( Critter& cr, uint16 drugPid )
{
    // Special drugs
    if( drugPid == PID_BOX_OF_DOUGHNUTS )
    {
        GameVar@ counter = GetLocalVar( LVAR_doughnuts_counter, cr.Id );
        if( valid( counter ) )
        {
            int max = counter.GetMax();
            if( counter < max - 1 )
                counter = counter.GetValue() + 1;
            else if( counter.GetValue() == max - 1 )
            {
                cr.SayMsg( SAY_NETMSG, TEXTMSG_TEXT, 70061 );             // Вы съели столько пончиков, что почуствовали себя немного сильнее. Переносимый вес увеличен на +1 пункт.}
                counter = max;
                cr.StatBase[ ST_CARRY_WEIGHT ] += LBS_TO_GRAMM( 1 );
            }
        }
    }
    if( drugPid == PID_JET_ANTIDOTE )
    {
        uint[] rates;
        uint count = cr.GetTimeEvents( PID_JET, null, null, rates );
        for( uint i = 0; i < count; i++ )
            DropDrug( cr, PID_JET, RATE_TO_STAGE( rates[ i ] ) );
        cr.EraseTimeEvents( PID_JET );
        if( count > 0 && cr.Addiction[ ADDICTION_JET ] != 0 )
        {
            cr.AddictionBase[ ADDICTION_JET ] = 0;
            cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_ADDICTION_END );
        }
        else
            cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_NOTHING_HAPPENS );
        return;
    }

    // Chem flags
    uint flags = 0;
    if( cr.Trait[ TRAIT_CHEM_RELIANT ] != 0 )
        flags |= DRUG_EFFECT_DIV2_WITHDRAWAL | DRUG_EFFECT_MUL2_ADDICTION;
    if( cr.Trait[ TRAIT_CHEM_RESISTANT ] != 0 )
        flags |= DRUG_EFFECT_DIV2_ADDICTION | DRUG_EFFECT_DIV2_DURATION;

    // Other drugs
    uint[] indexes;
    uint[] rates;
    uint count = cr.GetTimeEvents( drugPid, indexes, null, rates );
    int  index = GetDrugTableIndex( drugPid );

    // Check
    if( DrugEffects[ index + TABLE_DRUG_ADDICT ] >= 0 ) // Addiction perk aviability
    {
        uint positive = 0;
        uint negative = 0;
        for( uint i = 0; i < count; i++ )
        {
            uint stage = RATE_TO_STAGE( rates[ i ] );
            if( stage <= 1 )
                positive++;
            else if( stage == 2 )
                negative++;
        }

        if( positive >= 2 - negative / 2 )
        {
            int addict = DrugEffects[ index + TABLE_DRUG_ADDICT ];
            int addictProc = DrugEffects[ index + TABLE_DRUG_PROC ];
            if( FLAG( flags, DRUG_EFFECT_MUL2_ADDICTION ) )
                addictProc *= 2;
            if( FLAG( flags, DRUG_EFFECT_DIV2_ADDICTION ) )
                addictProc /= 2;
            if( cr.Addiction[ addict ] == 0 && Random( 1, 100 ) <= addictProc )
                cr.AddictionBase[ addict ] = 1;
            else
                cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_NOTHING_HAPPENS );
            return;
        }
    }

    // Clear active addictions
    uint deleted = 0;   // After erase indexes decrement on one position
    for( uint i = 0; i < count; i++ )
    {
        uint stage = RATE_TO_STAGE( rates[ i ] );
        if( stage >= 3 )
        {
            DropDrug( cr, drugPid, stage );
            cr.EraseTimeEvent( indexes[ i ] - deleted );
            deleted++;
        }
    }

    // Set critter time event
    cr.AddTimeEvent( "cte_Drug", 0, drugPid, FORM_RATE( 0, flags ) );
}

int GetDrugTableIndex( uint16 drugPid )
{
    int index = 0;
    switch( drugPid )
    {
    case PID_STIMPAK:
        index = 0;
        break;
    case PID_RADAWAY:
        index = 1;
        break;
    case PID_ANTIDOTE:
        index = 2;
        break;
case PID_RAD_X:
        index = 3;
        break;
case PID_SUPER_STIMPAK:
        index = 4;
        break;
case PID_JET_ANTIDOTE:
        index = 5;
        break;
case PID_HEALING_POWDER:
        index = 6;
        break;
case PID_HYPO:
        index = 7;
        break;
case PID_NUKA_COLA:
        index = 8;
        break;
case PID_BEER:
        index = 9;
        break;
case PID_BOOZE:
        index = 10;
        break;
case PID_GAMMA_GULP_BEER:
        index = 11;
        break;
case PID_ROENTGEN_RUM:
        index = 12;
        break;
case PID_ROT_GUT:
        index = 13;
        break;
case PID_MENTATS:
        index = 14;
        break;
case PID_BUFFOUT:
        index = 15;
        break;
case PID_PSYCHO:
        index = 16;
        break;
case PID_JET:
        index = 17;
        break;
case PID_MUTATED_FRUIT:
        index = 18;
        break;
    case PID_IGUANA_ON_A_STICK:
        index = 19;
        break;
    case PID_MEAT_ON_A_STICK:
        index = 20;
        break;
    case PID_COOKIE:
        index = 21;
        break;
    case PID_HYPO_POISON:
        index = 22;
        break;
    case PID_MUTATED_TOE:
        index = 23;
        break;
    case PID_KITTY_SEX_DRUG_AGILITY:
        index = 24;
        break;
    case PID_KITTY_SEX_DRUG_INTELLIGENCE:
        index = 25;
        break;
    case PID_KITTY_SEX_DRUG_STRENGTH:
        index = 26;
        break;
    case PID_MONUMENT_CHUNCK:
        index = 27;
        break;
    case PID_BOX_OF_DOUGHNUTS:
        index = 28;
        break;
    case PID_WATER_PURE:
        index = 29;
        break;
case PID_WATER_CLEAN:
        index = 30;
        break;
case PID_WATER_DIRTY:
        index = 31;
        break;
case PID_WATER_RAD:
        index = 32;
        break;
case PID_BRAHMIN_MEAT:
        index = 33;
        break;
case PID_GECKO_MEAT:
        index = 34;
        break;
case PID_BRAHMIN_STEAK:
        index = 35;
        break;
case PID_GECKO_STEAK:
        index = 36;
        break;
case PID_BEANS:
        index = 37;
        break;
case PID_RAVIOLI:
        index = 38;
        break;
case PID_CANNEDBEEF:
        index = 39;
        break;
default:
        break;
    }
    index *= 39;
    return index;
}

uint ProcessDrug( Critter& cr, uint16 drugPid, uint& rate )
{
    uint stage = RATE_TO_STAGE( rate );
    uint flags = RATE_TO_FLAGS( rate );

    if( cr.IsDead() )
        return REAL_MINUTE( 5 );               // Stop drug processing
    if( drugPid == PID_JET && stage >= 4 )
        return REAL_HOUR( 5 );                 // Only after Jet Antidote was used

    int  index = GetDrugTableIndex( drugPid );
    uint duration = 0;

    if( stage == 0 || // Instant effect
        stage == 1 || // Withdrawal
        stage == 2 || // Normalize
        stage == 3 || // Addiction begin
        stage == 4 )  // Addiction end
    {
        for( uint i = 0; i < 4; i++ )
        {
            int stat = DrugEffects[ index + TABLE_STAT( i ) ];
            int amount = DrugEffects[ index + TABLE_AMOUNT( i, stage ) ];
            if( i == 1 && DrugEffects[ index + TABLE_STAT( 0 ) ] == -2 )
                amount = Random( DrugEffects[ index + TABLE_AMOUNT( 0, stage ) ], amount );                                              // Take first
            if( stat < 0 )
                continue;

            int statVal = cr.Stat[ stat ];
            if( stat < STAT_EXT_BEGIN )
                cr.StatBase[ STAT_EXT_BEGIN + stat ] += amount;
            else if( stat == ST_CURRENT_HP )
            {
                cr.StatBase[ ST_CURRENT_HP ] = CLAMP( statVal + amount, -9999, cr.Stat[ ST_MAX_LIFE ] );
                if( amount < 0 && cr.Stat[ ST_CURRENT_HP ] < 0 )
                    cr.ToDead( Random( 0, 1 ) == 0 ? ANIM2_DEAD_FRONT : ANIM2_DEAD_BACK, null );
            }
            else if( stat == ST_POISONING_LEVEL )
                AffectPoison( cr, amount );                                        // cr.SetStat(ST_POISONING_LEVEL,CLAMP(statVal+amount,0,2000));
            else if( stat == ST_RADIATION_LEVEL )
                AffectRadiation( cr, amount );                                     // cr.SetStat(ST_RADIATION_LEVEL,CLAMP(statVal+amount,0,2000));
            else if( stat == ST_HAMBRE_LEVEL )
                AffectHambre( cr, amount );                                        // cr.SetStat(ST_RADIATION_LEVEL,CLAMP(statVal+amount,0,2000));
else
                continue;

            statVal = cr.Stat[ stat ] - statVal;
            if( statVal > 0 )
                cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_STAT_GAIN, "$name @msg game " + STR_PARAM_NAME( stat ) + "@$value" + statVal );
            else if( statVal < 0 )
                cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_STAT_LOSE, "$name @msg game " + STR_PARAM_NAME( stat ) + "@$value" + ( -statVal ) );
        }

        int addict = DrugEffects[ index + TABLE_DRUG_ADDICT ];
        if( stage == 0 )     // To withdrawal
        {
            duration = DrugEffects[ index + TABLE_DURATION( stage ) ];
            if( FLAG( flags, DRUG_EFFECT_DIV2_DURATION ) )
                duration /= 2;
            // Try set addiction perk
            int addictProc = DrugEffects[ index + TABLE_DRUG_PROC ];
            if( FLAG( flags, DRUG_EFFECT_MUL2_ADDICTION ) )
                addictProc *= 2;
            if( FLAG( flags, DRUG_EFFECT_DIV2_ADDICTION ) )
                addictProc /= 2;
            if( stage == 0 && addict >= 0 && Random( 1, 100 ) <= addictProc )
                cr.AddictionBase[ addict ] = 1;
        }
        else if( stage == 1 )     // To normalize
        {
            duration = DrugEffects[ index + TABLE_DURATION( stage ) ];
            if( FLAG( flags, DRUG_EFFECT_DIV2_DURATION ) )
                duration /= 2;
        }
        else if( stage == 2 && addict >= 0 && cr.Addiction[ addict ] != 0 ) // To addiction
        {
            // Find already processed addiction
            uint[] rates;
            uint count = cr.GetTimeEvents( drugPid, null, null, rates );
            bool isPresent = false;
            for( uint i = 0; i < count; i++ )
            {
                if( RATE_TO_STAGE( rates[ i ] ) >= 3 )
                {
                    isPresent = true;
                    break;
                }
            }
            if( not isPresent )
                duration = DrugEffects[ index + TABLE_DURATION( stage ) ];
        }
        else if( stage == 3 )     // To end of addiction
        {
            duration = DrugEffects[ index + TABLE_DURATION( stage ) ];
            if( FLAG( flags, DRUG_EFFECT_DIV2_WITHDRAWAL ) )
                duration /= 2;
        }
        else if( stage == 4 )     // End of addiction
        {
            cr.SayMsg( SAY_NETMSG, TEXTMSG_GAME, STR_DRUG_ADDICTION_END );
            if( addict >= 0 && cr.Addiction[ addict ] != 0 )
                cr.AddictionBase[ addict ] = 0;
        }
    }

    stage++;
    rate = FORM_RATE( stage, flags );
    return duration * 60;
}

void DropDrug( Critter& cr, uint16 drugPid, uint stage )
{
    if( stage == 0 || stage == 3 )
        return;                           // Instant effect not happens or already normalize or wait Addidional effect

    int index = GetDrugTableIndex( drugPid );

    if( stage == 1 || // Instant effect already
        stage == 2 || // Withdrawal already
        stage == 4 )  // Addiction already
    {
        for( uint i = 0; i < 4; i++ )
        {
            int stat = DrugEffects[ index + TABLE_STAT( i ) ];
            int amount = DrugEffects[ index + TABLE_AMOUNT( i, stage + ( stage == 1 ? -1 : 0 ) ) ]; // Turn
            if( stage == 1 )
                amount = -amount;
            if( stat < STAT_EXT_BEGIN )
                cr.StatBase[ STAT_EXT_BEGIN + stat ] += amount;
        }
    }
}

uint cte_Drug( Critter& cr, int identifier, uint& rate )
{
    return ProcessDrug( cr, identifier, rate );
}

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #3 on: August 28, 2017, 09:29:48 pm »
Just add the new drugpid to

const int[] DrugsIdentifiers
const int[] DrugEffects
and
int GetDrugTableIndex( uint16 drugPid )

DrugsEffects seems to be missing a whole lot of data from the list of drugs in the identifiers array. If those are the ones you added, you need to add ALL the corresponding effects to the drugEffects array in the specified order of GetDrugTableIndex
« Last Edit: August 28, 2017, 09:41:00 pm by devis »

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #4 on: August 29, 2017, 12:12:38 am »
Thanks for taking effort in helping me, but, I do know how to add drugs, I did add the drugs I wanted but removed them for testing purposes.

If you read the original post, you'll realize I explained why there are no drug effects.

I wasn't asking how to add new drugs. I was asking why Radaway had the Jet effect instead its own. Which is still a X-File I can't understand.

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #5 on: August 29, 2017, 12:25:21 am »
Did you make this change "index *= 39; " which i assumed was index *= 30 before?
« Last Edit: August 29, 2017, 12:32:52 am by devis »

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #6 on: August 29, 2017, 01:28:44 am »
Yes, absolutely. But I wasn't entirely sure if I had to set it to 39 or 40

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #7 on: August 29, 2017, 02:11:29 am »
change it back to 30

Re: drug table madness. Drugs.fos is broken. [old TLA SDK.]
« Reply #8 on: August 30, 2017, 11:31:27 am »
You were totally right. It doesn't make sense to me. BUT it worked. Added back the whole clusterf*ck of drugs and they're all working. Even tho they are over 50 and top index is 30. And best of all is jet is jet, buffout is buffout and so on. No more swapping effects between drugs.

Thank you very much