FOnline Development > Questions and Answers
drug table madness. Drugs.fos is broken. [old TLA SDK.]
Grey:
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!!?
devis:
Which revision sdk? Post the drug.fos and drug_data.fos if they exist.
Grey:
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: ---// 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 );
}
--- End code ---
devis:
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
Grey:
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.
Navigation
[0] Message Index
[#] Next page
Go to full version