i've hooked up the generic "alive band member" iterator to the main loop in BMupdate_all.
i also put the body of the loop in its own function: BMupdate_each(int a);
then i collapsed all the calls in BMupdate_each to inline code to create a new version called BMupdate_each2
the iterators....
int BM_alive_num,BM_active_num;
int first_alive_bandmember()
{
int a;
for (a=0; a<maxcavemen; a++)
{
if (cm[a].active == 0)
{
continue;
}
if (cm[a].alive == 0)
{
continue;
}
BM_alive_num=a;
return(a);
}
return(-1);
}
int next_alive_bandmember()
{
int a;
for (a=BM_alive_num+1; a<maxcavemen; a++)
{
if (cm[a].active == 0)
{
continue;
}
if (cm[a].alive == 0)
{
continue;
}
BM_alive_num=a;
return(a);
}
return(-1);
}
int first_active_bandmember()
{
int a;
for (a=0; a<maxcavemen; a++)
{
if (cm[a].active == 0)
{
continue;
}
BM_active_num=a;
return(a);
}
return(-1);
}
int next_active_bandmember()
{
int a;
for (a=BM_active_num+1; a<maxcavemen; a++)
{
if (cm[a].active == 0)
{
continue;
}
BM_active_num=a;
return(a);
}
return(-1);
}
here's the new BMupdate_all:
// must call move_rafts first!
void BMupdate_all()
{
int a;
a=first_alive_bandmember();
while (a!=-1)
{
BMupdate_each(a);
a=next_alive_bandmember();
}
}
and now, for a wall of spaghetti code - the new BMupdate_each2 with all the code pulled into one function.
this thing is probably similar to that 32,000 line (or whatever it was) update function mentioned previously....
it seems to be bigger, uglier, and probably more work to maintain. one function, 905 line of code.
void BMupdate_each2(int a)
{
int b,c,e,mx,mz,d,num,f,chance,rng;
float h,x,y,z;
char s[100];
// do update stuff here - do global frame
// decrease fatigue
if ((cm[a].moved==0) && (!cm[a].paddling) && (action[cm[a].current_action].energy))
{
cm[a].fatigue-=7; // reduce fatigue.
if (cm[a].fatigue<0) cm[a].fatigue=0;
}
// model attack
if (cm[a].attacking)
{
cm[a].attack_counter++;
if (on_drug(a,GAHMUHROOT)) c=atktime*3/4; else c=atktime;
if (cm[a].attack_counter >= c)
{
cm[a].attacking=0;
}
else if (cm[a].attack_counter==5) resolve_attack(a);
}
// model surprise
if (cm[a].suprised)
{
cm[a].suprise_counter++;
if (cm[a].suprise_counter>60-xpbonus(cm[a].xp[HUNTING])) cm[a].suprised=0;
}
// model full fatigue
if (cm[a].fatigue >= 100000)
{
if (cm[a].current_action != MOVE) msg("You're so fatigued you have to stop and rest!");
// dont resume the following actions w/ friendly cavemen, as they may have wandered off while band member was resting
if ( (cm[a].current_action != TEACHCAVEMAN) && (cm[a].current_action != TELLJOKE) && (cm[a].current_action != TELLSTORY) ) pushaction2(a);
b=gamespeed;
setaction(a,REST);
gamespeed=b;
cm[a].action_x=0; // no bedding
}
// run bamdmember
if (a!=cm0)
{
if ( badguys_nearby(a) && (cm[a].current_action != DONOTHING) ) // halt action if badguys near
{
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
}
if (cm[a].current_action==DONOTHING)
{
cm[a].is_blocking=0;
if (cm[a].collision_recovery)
{
move_bandmember_collision_recovery(a);
}
else
{
set_bandmember_tgt(a);
steer_bandmember(a);
move_bandmember(a);
do_bandmember_atk(a);
}
}
else
{
b=cm0;
cm0=a;
doactionmodeB(a);
cm0=b;
}
}
// model raft movement
if (cm[a].location == ONRAFT)
{
if (cm[a].current_action != MOVERAFT)
{
b=cm[a].raftnum;
cm[a].x+=worldobj[b].dx;
cm[a].z+=worldobj[b].dz;
normalize_location( &cm[a].mx, &cm[a].mz, &cm[a].x, &cm[a].z );
cm[a].y=heightmap(cm[a].mx,cm[a].mz,cm[a].x,cm[a].z);
}
}
// model paddling fatigue
if (cm[a].paddling)
{
cm[a].fatigue+=1;
if (cm[a].fatigue>100000) cm[a].fatigue=100000;
}
// model falling
if (cm[a].falling)
{
cm[a].vy+=-g2;
cm[a].x+=cm[a].vx;
cm[a].y+=cm[a].vy;
cm[a].z+=cm[a].vz;
h=heightmap( cm[a].mx, cm[a].mz, cm[a].x,cm[a].z);
if (cm[a].y <= h ) bandmember_hit_ground(a,h);
}
// model sneak detection
if ( (a % 15 == frame) && (cm[a].sneak_state!=0) )
{
if (cm[a].sneak_state==3)
{
if (! bandmember_targeted(a)) cm[a].sneak_state=1;
}
else // states 1 & 2
{
switch (detection_state(a))
{
case 0: cm[a].sneak_state=1; // sneaking - undetected
break;
case 1: cm[a].sneak_state=2; // sneaking - detected - non-hostile
break;
case 2: cm[a].sneak_state=3; // sneaking - detected - hostile
break;
}
}
}
if (frame != 0)
{
return;
}
// do global second
// model fatgue due to damage
if (
(! on_drug(a,MUHAHBOOLEAF)) &&
(! on_drug(a,YAHBEEBARK)) &&
(! on_drug(a,BAHYUHSEED)) &&
(! on_drug(a,GAHMUHROOT))
)
{
cm[a].fatigue+=10*cm[a].dmg/cm[a].hp;
if (cm[a].fatigue>=100000) cm[a].fatigue=100000;
}
// model fatigue due to encumberance
if ( (!on_drug(a,MUHAHBOOLEAF)) && (! on_drug(a,BAHYUHSEED)) )
{
cm[a].fatigue+=10*encumberance(a)/maxencumberance(a);
if (cm[a].fatigue>=100000) cm[a].fatigue=100000;
}
// run quests
for (b=0; b<maxquests; b++)
{
if (! cm[a].quest[b].active) continue;
run_quest(a,b);
}
// clear rock shelter encounter flags
mx=cm[a].mx;
mz=cm[a].mz;
if ( map[mx][mz].cliffs)
{
for (e=60000; e<65000; e++)
{
if (crh2[e].mx != mx) continue;
if (crh2[e].mz != mz) continue;
if (crh2[e].encounter_checked)
{
if (first_bandmember_near_cave_or_rockshelter(mx,mz,e,300) == -1)
{
remove_CRH_cavemen(2,mx,mz,e); // 2 = rockshelter housetype removes friendly cavemen only!
crh2[e].encounter_checked=0;
if ((crh2[e].owner_type==HOSTILECAVE) && (hostile_CRH_encounter_underway) )
{
if ((! hostile_fled_CRH_encounter) && (! hostile_in_mapsq(a))) crh2[e].owner_type=EMPTYCAVE;
hostile_CRH_encounter_underway=0;
hostile_fled_CRH_encounter=0;
}
}
}
}
}
// check rock shelter encounters
mx=cm[a].mx;
mz=cm[a].mz;
if ( map[mx][mz].cliffs)
{
for (e=60000; e<65000; e++)
{
if (crh2[e].mx != mx) continue;
if (crh2[e].mz != mz) continue;
if (crh2[e].encounter_checked) continue;
if ( BBdist( (int)cm[a].x, (int)cm[a].z, crh2[e].x,crh2[e].z) > 75) continue; // trigger at 75, reset at 300
crh2[e].encounter_checked=1;
switch ( crh2[e].owner_type )
{
case ANIMALCAVE: do_cave_animal_encounter(a); break;
case FRIENDLYCAVE:
if (crh2[e].npc_ownerID == -1) // no npc assigned to rockshelter yet, so assign one
{
num=dice(10);
for (b=0; b<num; b++)
{
x=crh2[e].x-20.0f+(float)b*10.0f;
z=crh2[e].z+40.0f;
y=heightmap(mx,mz,x,z);
d=add_caveman(mx,mz,x,y,z,0,0);
if (d != -1)
{
animal[a].butchered=new_npc();
if (b==0) crh2[e].npc_ownerID=animal[d].butchered;
npc[animal[d].butchered].house_type=2; // house type: 0=unassigned 1=cave 2=rockshelter 3=hut
npc[animal[d].butchered].house_mx=mx;
npc[animal[d].butchered].house_mz=mz;
npc[animal[d].butchered].house_index=e;
animal[d].sacrificed=1; // 1= they're a CRH caveman
}
}
}
else
{
c=0;
for (b=0; b<maxnpcs; b++)
{
if (! npc[b].active) continue;
if (npc[b].house_type != 2) continue; // if not rockshelter
if (npc[b].house_mx != mx) continue;
if (npc[b].house_mz != mz) continue;
if (npc[b].house_index != e) continue;
x=crh2[e].x-20.0f+(float)c*10.0f;
z=crh2[e].z+40.0f;
y=heightmap(mx,mz,x,z);
d=add_caveman(mx,mz,x,y,z,0,0);
if (d != -1)
{
animal[d].butchered=b;
animal[d].sacrificed=1; // 1= they're a CRH caveman
}
c++;
}
}
msg("You encounter cavemen from the nearby rockshelter!");
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
gamespeed=0;
break;
case HOSTILECAVE: add_hostile_cavemen(a,0);
msg("You encounter cavemen from the nearby rockshelter!");
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
gamespeed=0;
hostile_CRH_encounter_underway=1;
hostile_fled_CRH_encounter=0;
break;
case PLAYERCAVE: if (dice(10000)<=1000) do_cave_animal_encounter(a); break;
}
}
}
// clear cave encounter flags
mx=cm[a].mx;
mz=cm[a].mz;
if ((map[mx][mz].elevation == 2) || (map[mx][mz].elevation == 3))
{
for (f=0; f<numcaves[mx][mz]; f++)
{
e=caveindex[mx][mz][f];
if (crh2[e].encounter_checked)
{
if (first_bandmember_near_cave_or_rockshelter(mx,mz,e,300) == -1)
{
remove_CRH_cavemen(1,mx,mz,e); // 1 = cave housetype removes friendly cavemen only!
crh2[e].encounter_checked=0;
if ((crh2[e].owner_type==HOSTILECAVE) && (hostile_CRH_encounter_underway) )
{
if ((! hostile_fled_CRH_encounter) && (! hostile_in_mapsq(a))) crh2[e].owner_type=EMPTYCAVE;
hostile_CRH_encounter_underway=0;
hostile_fled_CRH_encounter=0;
}
}
}
}
for (e=0; e<60000; e++)
{
if (crh2[e].mx != mx) continue;
if (crh2[e].mz != mz) continue;
if (crh2[e].encounter_checked)
{
if (first_bandmember_near_cave_or_rockshelter(mx,mz,e,300) == -1)
{
remove_CRH_cavemen(1,mx,mz,e); // 1 = cave housetype removes friendly cavemen only!
crh2[e].encounter_checked=0;
if ((crh2[e].owner_type==HOSTILECAVE) && (hostile_CRH_encounter_underway) )
{
if ((! hostile_fled_CRH_encounter) && (! hostile_in_mapsq(a))) crh2[e].owner_type=EMPTYCAVE;
hostile_CRH_encounter_underway=0;
hostile_fled_CRH_encounter=0;
}
}
}
}
}
// check cave encounters
mx=cm[a].mx;
mz=cm[a].mz;
if ((map[mx][mz].elevation == 2) || (map[mx][mz].elevation == 3))
{
for (f=0; f<numcaves[mx][mz]; f++)
{
e=caveindex[mx][mz][f];
if (crh2[e].encounter_checked) return;
if ( BBdist( (int)cm[a].x, (int)cm[a].z, crh2[e].x,crh2[e].z) > 75) continue; // trigger at 75, reset at 300
crh2[e].encounter_checked=1;
switch ( crh2[e].owner_type )
{
case ANIMALCAVE: do_cave_animal_encounter(a); break;
case FRIENDLYCAVE:
if (crh2[e].npc_ownerID == -1) // no npc assigned to cave yet, so assign one
{
num=dice(10);
for (b=0; b<num; b++)
{
x=crh2[e].x-20.0f+(float)b*10.0f;
z=crh2[e].z+40.0f;
y=heightmap(mx,mz,x,z);
d=add_caveman(mx,mz,x,y,z,0,0);
if (d != -1)
{
animal[d].butchered=new_npc();
if (b==0) crh2[e].npc_ownerID=animal[d].butchered;
npc[animal[d].butchered].house_type=1; // house type: 0=unassigned 1=cave 2=rockshelter 3=hut
npc[animal[d].butchered].house_mx=mx;
npc[animal[d].butchered].house_mz=mz;
npc[animal[d].butchered].house_index=e;
animal[d].sacrificed=1; // 1= they're a CRH caveman
}
}
}
else
{
c=0;
for (b=0; b<maxnpcs; b++)
{
if (! npc[b].active) continue;
if (npc[b].house_type != 1) continue; // if not cave
if (npc[b].house_mx != mx) continue;
if (npc[b].house_mz != mz) continue;
if (npc[b].house_index != e) continue;
x=crh2[e].x-20.0f+(float)c*10.0f;
z=crh2[e].z+40.0f;
y=heightmap(mx,mz,x,z);
d=add_caveman(mx,mz,x,y,z,0,0);
if (d != -1)
{
animal[d].butchered=b;
animal[d].sacrificed=1; // 1= they're a CRH caveman
}
c++;
}
}
msg("You encounter cavemen from the nearby cave!");
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
gamespeed=0;
break;
case HOSTILECAVE: add_hostile_cavemen(a,0);
msg("You encounter cavemen from the nearby cave!");
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
gamespeed=0;
hostile_CRH_encounter_underway=1;
hostile_fled_CRH_encounter=0;
break;
case PLAYERCAVE: if (dice(10000)<=1000) do_cave_animal_encounter(a); break;
}
}
}
// clear hut encounter flags
mx=cm[a].mx;
mz=cm[a].mz;
for (e=65000; e<num_crhs; e++)
{
if (! crh2[e].active) continue;
if (crh2[e].mx != mx) continue;
if (crh2[e].mz != mz) continue;
if (crh2[e].encounter_checked)
{
if (! bandmember_near_hut(e)) // if no bandmember <= 300 from hut
{
remove_CRH_cavemen(3,mx,mz,0); // 3 = hut housetype removes friendly cavemen only!
crh2[e].encounter_checked=0;
}
}
}
// check hut encounters
mx=cm[a].mx;
mz=cm[a].mz;
for (e=65000; e<num_crhs; e++)
{
if (! crh2[e].active) continue;
if (crh2[e].mx != mx) continue;
if (crh2[e].mz != mz) continue;
if (crh2[e].encounter_checked) continue;
if ( BBdist( (int)cm[a].x, (int)cm[a].z, crh2[e].x,crh2[e].z) > 75) continue; // trigger at 75, reset at 300
crh2[e].encounter_checked=1;
switch ( crh2[e].owner_type )
{
case FRIENDLYCAVE:
if (crh2[e].npc_ownerID == -1) // no npc assigned to hut yet, so assign one
{
num=dice(10);
for (b=0; b<num; b++)
{
x=crh2[e].x-20.0f+(float)b*10.0f;
z=crh2[e].z+30.0f;
y=heightmap(mx,mz,x,z);
d=add_caveman(mx,mz,x,y,z,0,0);
if (d != -1)
{
animal[d].butchered=new_npc();
if (b==0) crh2[e].npc_ownerID=animal[d].butchered;
npc[animal[d].butchered].house_type=3; // house type: 0=unassigned 1=cave 2=rockshelter 3=hut
npc[animal[d].butchered].house_mx=mx;
npc[animal[d].butchered].house_mz=mz;
animal[d].sacrificed=1; // 1= they're a CRH caveman
}
}
}
else
{
c=0;
for (b=0; b<maxnpcs; b++)
{
if (! npc[b].active) continue;
if (npc[b].house_type != 3) continue; // if not hut
if (npc[b].house_mx != mx) continue;
if (npc[b].house_mz != mz) continue;
x=crh2[e].x-20.0f+(float)c*10.0f;
z=crh2[e].z+30.0f;
y=heightmap(mx,mz,x,z);
d=add_caveman(mx,mz,x,y,z,0,0);
if (d != -1)
{
animal[d].butchered=b;
animal[d].sacrificed=1; // 1= they're a CRH caveman
}
c++;
}
}
msg("You encounter cavemen from the nearby hut!");
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
gamespeed=0;
break;
case HOSTILECAVE: add_hostile_cavemen(a,0);
msg("You encounter cavemen from the nearby hut!");
if (cm[a].current_action == MOVE) adjust_bandmember_location(a);
setaction(a,DONOTHING);
gamespeed=0;
break;
case PLAYERCAVE: if (dice(10000)<=1000) do_animal_encounter(a); break;
}
}
// check hut takeover
for (b=65000; b<num_crhs; b++)
{
if (! crh2[b].active) continue;
if (! crh2[b].encounter_checked) continue;
if (crh2[b].mx != cm[a].mx) continue;
if (crh2[b].mz != cm[a].mz) continue;
if (BBdist( (int)cm[a].x, (int)cm[a].z, crh2[b].x, crh2[b].z ) > 50) continue;
if (cavemen_near_hut(b)) continue;
msg("The nearby hut has been abandoned !");
if (cm[a].has_perm_shelter) Znewmenu("Abandon your hut and take this one over ?");
else Znewmenu("Takeover abandoned hut ?");
Zaddmenu("Yes");
Zaddmenu("No");
if (menu(2)==1)
{
// create perm shelter where hut is
cm[a].has_perm_shelter=1;
cm[a].shel_mx=cm[a].mx;
cm[a].shel_mz=cm[a].mz;
cm[a].shel_x=crh2[b].x;
cm[a].shel_z=crh2[b].z;
cm[a].perm_shel_quality=100;
}
crh2[b].active=0;
pcrh2[b].active=0;
// sort_and_index_huts("Updating huts");
index_huts2();
cm[a].mood+=10;
ulim(&cm[a].mood,100);
}
// check climbing animals
if (cm[a].location == UPATREE)
{
check_animal_climbing_up(a);
}
if (second != 0)
{
return;
}
// do global minute
// check animal encounters
b=animal_encounter_chance();
if (dice(10000) <= b)
{
do_animal_encounter(a);
}
// check caveman encounters
if (dice(10000) > 10)
{
return;
}
b=caveman_encounter_chance(a);
if (dice(10000) > b)
{
return;
}
do_caveman_encounter(a);
// model intox
for (b=0; b<maxdrugs; b++)
{
if (! cm[a].drug[b].active) continue;
cm[a].drug[b].age++;
if (cm[a].drug[b].age>400)
{
switch(cm[a].drug[b].type)
{
case MUHAHBOOLEAF: cm[a].dex--;
cm[a].sleep-=50;
llim(&cm[a].sleep,0);
cm[a].fatigue+=50000;
ulim(&cm[a].fatigue,100000);
break;
case BOOYEEBEEBERRY: cm[a].intelligence-=2;
break;
case GAHYEEMOOGUHFLOWER: cm[a].sleep-=10;
llim(&cm[a].sleep,0);
break;
case YAHBEEBARK: cm[a].mood-=40;
llim(&cm[a].mood,0);
break;
case BAHYUHSEED: cm[a].str-=3;
cm[a].sleep-=50;
llim(&cm[a].sleep,0);
cm[a].fatigue+=50000;
ulim(&cm[a].fatigue,100000);
break;
case GAHMUHROOT: cm[a].speed-=2;
cm[a].sleep-=50;
llim(&cm[a].sleep,0);
cm[a].fatigue+=50000;
ulim(&cm[a].fatigue,100000);
break;
}
cm[a].drug[b].active=0;
}
}
// extinguish torches
for (b=0; b<maxobjrecs; b++)
if ( (cm[a].stuff[b].active) && (cm[a].stuff[b].type==LITTORCH) )
{
cm[a].stuff[b].qual--;
if (cm[a].stuff[b].qual < 1) cm[a].stuff[b].active=0;
}
if (minute%7 == 0)
{
// reduce hygiene due to movement
if (cm[a].moved)
{
cm[a].hygiene--;
if (cm[a].running) cm[a].hygiene--;
if (cm[a].hygiene<0) cm[a].hygiene=0;
}
}
if (minute%10 == 0)
{
// reduce water
cm[a].water--;
if (cm[a].water<0) cm[a].water=0;
// reduce sleep
cm[a].sleep--;
if (cm[a].sleep<=0)
{
cm[a].sleep=0;
if (cm[a].current_action != SLEEP)
{
setaction(a,SLEEP); // sleep
cm[a].actiondata[0]=0;
cm[a].actiondata[1]=cm[a].sleep; // save old sleep value for mood check when they wake up
cm[a].actiondata[2]=100;
if ((cm[a].dmg>0) || (cm[a].has_disease))
{
if (num_carried(a,MEDHERB,ANYQUALITY) > 0)
{
remove_best(a,MEDHERB);
cm[a].actiondata[3]=1; // using med herbs
}
else cm[a].actiondata[3]=0; // not using med herbs
}
else cm[a].actiondata[3]=0; // not using med herbs
msg("You pass out from lack of sleep!");
}
}
}
if (minute%15 == 0)
{
// reduce food
cm[a].food--;
if (cm[a].food<0) cm[a].food=0;
// affect mood
if (! on_drug(a,MUHAHBOOLEAF))
{
if (cm[a].water<1)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
if (cm[a].food<1)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
if ( !on_drug(a,YAHBEEBARK) && !on_drug(a,BAHYUHSEED))
{
if (cm[a].dmg>cm[a].hp/2)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
}
if (cm[a].has_disease)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
if (cm[a].hygiene<1)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
if (encumberance(a)>3*maxencumberance(a)/4)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
if ( (is_raining) && (!has_shelter(a)) && !on_drug(a,GAHMUHROOT) && ! on_drug(a,MUHAHBOOLEAF) ) // rain
{
cm[a].mood-=2;
if (cm[a].mood<0) cm[a].mood=0;
}
b=cm0;
cm0=a;
if ( (windchill(a) < 60.0f) && (!has_shelter(a)) && (! near_fire()) && !on_drug(a,GAHMUHROOT) && !on_drug(cm0,MUHAHBOOLEAF) ) // cold
{
cm[a].mood-=2;
if (cm[a].mood<0) cm[a].mood=0;
}
cm0=b;
if (temp_at(a) > 80.0f) // heat
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
if (cm[a].social<1) // make social affect mood
if (dice(10000) <= 23)
{
cm[a].mood--;
if (cm[a].mood<0) cm[a].mood=0;
}
}
}
if (minute != 0)
{
return;
}
// do global hour
// reduce hygiene
if (cm[a].hygiene>=1) cm[a].hygiene--;
// model dehydration
if (cm[a].water<1)
{
if (dice(100)<=12)
{
cm[a].dmg++;
cm[a].mood-=2;
llim(&cm[a].mood,0);
msg("You take damage from dehydration!");
if (cm[a].dmg>=cm[a].hp)
{
msg("You died of dehydration!");
kill_bandmember(a);
}
}
}
// model food spoilage
for (b=0; b<maxobjrecs; b++)
{
if (!cm[a].stuff[b].active) continue;
if (object[cm[a].stuff[b].type].spoilchance==0) continue;
if (dice(10000) >= object[cm[a].stuff[b].type].spoilchance) continue;
cm[a].stuff[b].qual-=object[cm[a].stuff[b].type].spoilrate;
if (cm[a].stuff[b].qual<1)
{
cm[a].stuff[b].active=0;
strcpy_s(s,100,"Some of your ");
strcat_s(s,100,object[cm[a].stuff[b].type].name);
strcat_s(s,100," spoiled!");
msg(s);
}
}
// model exposure
if (exposed(a))
{
if (dice(10000) <= 1000)
{
cm[a].dmg++;
cm[a].mood-=2;
llim(&cm[a].mood,0);
msg("You take damage from exposure to cold!");
if (cm[a].dmg >= cm[a].hp)
{
msg("You died from exposure to cold!");
kill_bandmember(a);
}
}
}
// model heatstroke
if (
(temp_at(a) > 100) &&
((cm[a].location==OUTSIDE) && (map[cm[a].mx][cm[a].mz].coverage!=WOODS)) &&
((cm[a].location==OUTSIDE) && (map[cm[a].mx][cm[a].mz].coverage!=JUNGLE)) &&
(! has_shelter(a)) &&
(dice(10000) <= 1000)
)
{
cm[a].dmg++;
cm[a].mood-=2;
llim(&cm[a].mood,0);
msg("You take damage from heatstroke!");
if (cm[a].dmg >= cm[a].hp)
{
msg("You died from heatstroke!");
kill_bandmember(a);
}
}
// model drown in flood
if (watertable>6.0f) // model drowning in floods
if(watertable>heightmap(cm[a].mx,cm[a].mz,cm[a].x,cm[a].z)+7.0f)
{
msg("You have been swept away by flood waters and drown!");
kill_bandmember(a);
}
// model wear n tear of clothing etc
for (b=0; b<maxobjrecs; b++)
{
if (!cm[a].stuff[b].active) continue;
switch(cm[a].stuff[b].type)
{
case BOOTS:
case HAT:
case MITTENS:
case CLOAK:
if ( is_raining && ! has_shelter(a) ) chance = 1000;
else chance = 462;
if (dice(10000) > chance) break;
cm[a].stuff[b].qual--;
if (cm[a].stuff[b].qual>0) break;
Ss("Your ");
Sa(object[cm[a].stuff[b].type].name);
Sa(" wore out!");
msg(S);
cm[a].stuff[b].active=0;
break;
}
}
// model perm shelter raids
if (cm[a].has_perm_shelter)
{
if (dice(10000) <= 100)
{
chance = 200 - xpbonus(cm[a].xp[CAMOFLAGE]);
rng=rng2closest_hostile_CRH(cm[a].shel_mx,cm[a].shel_mz);
if (rng<1) rng=1;
chance+=200/rng;
if (dice(10000) <= chance) raid_perm_shelter(a);
}
}
// moodboost nature lovers
if (
(dice(10000) <= 2500) &&
(has_interest(a,I_NATURE)) &&
( (map[cm[a].mx][cm[a].mz].coverage == WOODS) || (map[cm[a].mx][cm[a].mz].coverage == JUNGLE) || (map[cm[a].mx][cm[a].mz].rocks) )
)
{
cm[a].mood++;
ulim(&cm[a].mood,100);
}
if (hour%2 == 0)
{
// model damage due to illness
if ( (cm[a].has_disease) && (dice(1000) < 100-xpbonus(cm[a].xp[HEALING])) )
{
cm[a].dmg++;
cm[a].mood-=2;
llim(&cm[a].mood,0);
msg("You take damage from being sick!");
if (cm[a].dmg>=cm[a].hp)
{
msg("You died from an illness!");
kill_bandmember(a);
}
}
}
if (((hour>7)&&(hour<19)))
{
// check quest encounters
if ( (at_friendly_CRH(a)) && (num_friendlies() > 0) && (dice(10000) <= 1000) ) do_quest_encounter(a);
}
if (hour != 0)
{
return;
}
// do global day
// model starvation
if ( (cm[a].food<1) && (dice(100)<=42) )
{
cm[a].dmg++;
msg("You take damage from starvation!");
cm[a].mood-=5;
llim(&cm[a].mood,0);
if (cm[a].dmg>=cm[a].hp)
{
msg("You died of starvation!");
kill_bandmember(a);
}
}
// model getting sick
if (cm[a].hygiene<1) b=100; else b=20; // low hygiene increases chance
b-=cm[a].con; // constitution decreases chance
if (exposed(a) || exposed2(a)) b+=300; // exposure increases chance
if (dice(1000)<b)
{
cm[a].has_disease=1;
msg("You've caught an illness!");
cm[a].mood-=10;
llim(&cm[a].mood,0);
}
// model background radiation - IE ageing
if (dice(10000) <= 3)
{
msg("You suffer aging from background radiation!");
cm[a].hp--;
cm[a].mood-=10;
llim(&cm[a].mood,0);
if ( (cm[a].hp<1) || (cm[a].dmg>=cm[a].hp) )
{
msg("Background radiation (old age) killed you!");
kill_bandmember(a);
}
}
// model permanent shelter weathering
if ( cm[a].has_perm_shelter)
{
if (dice(10000) <= 6000)
{
cm[a].perm_shel_quality--;
if (cm[a].perm_shel_quality < 1)
{
cm[a].has_perm_shelter=0;
msg("Your shelter has weathered away!");
}
}
}
// zero god relations
for (b=0; b<8; b++)
{
if (cm[a].god[b] > 0) cm[a].god[b]--;
if (cm[a].god[b] < 0) cm[a].god[b]++;
}
// reduce social
cm[a].social-=5;
llim(&cm[a].social,0); // make social go down by 5 per day
// model traps
for (b=0; b<maxtraps; b++)
{
if (!cm[a].trap[b].active) continue;
cm[a].trap[b].age++;
if (cm[a].trap[b].age>30)
{
cm[a].trap[b].active=0;
continue;
}
switch(cm[a].trap[b].status)
{
case 0: c=dice(10000);
if (c<=500) cm[a].trap[b].status=1; // caught animal
else if (c<=1000) cm[a].trap[b].status=2; // trap sprung, no animal caught
break;
case 1: cm[a].trap[b].daystrapped++;
if (cm[a].trap[b].daystrapped > 5) cm[a].trap[b].status=2; // trap sprung, no animal caught (rotted away)
break;
}
}
// model skill reduction
for (b=0; b<maxskilltypes; b++)
{
if (cm[a].xp[b] <1 ) continue;
c=cm[a].xp[b];
c/=100;
if (c<1) continue;
if (dice(10000) > 274) continue; // works out to -1%, 10x / year on avg.
cm[a].xp[b]-=c;
}
}
compare that to BMupdate_each:
void BMupdate_each(int a)
{
// do update stuff here - do global frame
BMdecrease_fatigue(a);
BMmodel_attack(a);
BMmodel_surprise(a);
BMmodel_full_fatigue(a);
run_bandmember(a);
BMmodel_raft_movement(a);
BMmodel_paddling_fatigue(a);
BMmodel_falling(a);
BMmodel_sneak_detection(a);
if (frame != 0)
{
return;
}
// do global second
BMmodel_fatigue_dueto_damage(a);
BMmodel_fatigue_dueto_encumbrance(a);
BMrun_quests(a);
BMclear_rockshelter_enccouter_flags(a);
BMcheck_rockshelter_encounters(a);
BMclear_cave_encounter_flags(a);
BMcheck_cave_encounters(a);
BMclear_hut_encouter_flags(a);
BMcheck_hut_encounters(a);
BMcheck_hut_takeover(a);
BMcheck_climbing_animals(a);
if (second != 0)
{
return;
}
// do global minute
BMcheck_animal_encounters(a);
BMcheck_caveman_encounters(a);
BMmodel_intox(a);
BMextinguish_torches(a);
if (minute%7 == 0)
{
BMreduce_hygiene_dueto_movement(a);
}
if (minute%10 == 0)
{
BMreduce_water(a);
BMreduce_sleep(a);
}
if (minute%15 == 0)
{
BMreduce_food(a);
BMaffect_mood(a);
}
if (minute != 0)
{
return;
}
// do global hour
BMreduce_hygiene(a);
BMmodel_dehydration(a);
BMmodel_food_spoilage(a);
BMmodel_exposure(a);
BMmodel_heatstroke(a);
BMmodel_drown_in_flood(a);
BMmodel_wearNtear(a);
BMmodel_perm_shelter_raids(a);
BMmoodboost_nature_lover(a);
if (hour%2 == 0)
{
BMmodel_damage_dueto_illness(a);
}
if (((hour>7)&&(hour<19)))
{
BMcheck_quest_encounters(a);
}
if (hour != 0)
{
return;
}
// do global day
BMmodel_starvation(a);
BMmodel_getting_sick(a);
BMmodel_background_radiation(a);
BMmodel_perm_shel_weathering(a);
BMzero_god_relations(a);
BMreduce_social(a);
BMmodel_traps(a);
BMmodel_skill_reduction(a);
}
BMupdate_each seems much clearer to me.
Although i'm technically not optimizing here, while i have everything setup already i might as well put timers on the two update_each functions just for fun.