The simplest of tasks...

Started by
6 comments, last by l0calh05t 10 years, 5 months ago

I now understand why games tend to take a very simplistic approach to reloading. I wanted to be clever, these two functions are a very roundabout way of incrementing one counter and decrementing another:


void updateWeaponLoadState(characterUnit_t *character)
{
int fireMode = 0; // FIXME - retrieve this from player structure
int loadType = character->weaponSlot[character->ps.weapon].loadType;
 
if (character->ps.magazineAmmo[character->ps.weapon] + character->ps.chamberedAmmo[character->ps.weapon] <= 0)
{ // No ammo, switch to empty state unless we're trying to reload
if (character->ps.weaponLoadState[character->ps.weapon] != RELOADSTATE_REMOVING_OLD_AMMO
&& character->ps.weaponLoadState[character->ps.weapon] != RELOADSTATE_ADDING_NEW_AMMO
&& character->ps.weaponLoadState[character->ps.weapon] != RELOADSTATE_OPENING
&& character->ps.weaponLoadState[character->ps.weapon] != RELOADSTATE_CLOSING)
{ // We not removing an empty mag or putting a new mag in at the moment, so set state to empty
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_EMPTY;
return;
}
}
 
if (character->weaponSlot[character->ps.weapon].shotsPerTrigger[fireMode] > 0)
{ // We're a single shot or burst weapon...
if (isWeaponManuallyCockedAfterShot(character) && character->ps.shotsRemaining == 0)
{ // ... that needs to be manually recocked after firing, and has finished firing
if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_COCKING && character->ps.weaponTime <= GameTime)
{ // We've completed the cocking sequence, go back to ready state
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_READY; // Set up to ready, and take a round from mag to chamber
character->ps.chamberedAmmo[character->ps.weapon]++; // FIXME - more/less than one round?
character->ps.magazineAmmo[character->ps.weapon]--;
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_FIRING)
{ // Weapon is not cocked, do it now.
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_COCKING;
// FIXME - cocking time could perhaps be affected by character stats.
character->ps.weaponTime = GameTime + character->weaponSlot[character->ps.weapon].cockingTime; 
}
}
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_FIRING && character->ps.weaponTime <= GameTime)
{ // An automatic or semi-automatic weapon that still has some ammo, and should be ready to fire again
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_READY;  // Set to ready, and take a round from mag to chamber
character->ps.chamberedAmmo[character->ps.weapon]++; // FIXME - more/less than one round?
character->ps.magazineAmmo[character->ps.weapon]--;
return;
}
 
if (character->ps.weaponState != WEAPONSTATE_RAISING &&
character->ps.weaponState != WEAPONSTATE_LOWERING &&
character->ps.weaponState != WEAPONSTATE_DROPPED)
{ // We're in a state where reloading is allowed
// Do these checks again, just in case something weird happened
if (character->ps.magazineAmmo[character->ps.weapon] >= character->weaponSlot[character->ps.weapon].magazineSize)
{ // Already a full mag, don't reload
return;
}
if (character->ps.shotsRemaining > 0)
{ // Don't reload if we're still trying to fire a burst
return;
}
// FIXME - Make sure we have ammo to put in our weapon
 
character->ps.weaponState = WEAPONSTATE_RELOADING;
 
if (character->ps.weaponTime <= GameTime)
{ // Ready to move to the next phase of our reload
if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_READY)
{ // we've finished reloading apparently?
character->ps.weaponState = WEAPONSTATE_READY;
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_REMOVING_OLD_AMMO)
{ // For any weapon type, adding new ammo will directly follow in from removing old
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_ADDING_NEW_AMMO;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].magInsertTime;
character->ps.magazineAmmo[character->ps.weapon] = 0;
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_ADDING_NEW_AMMO)
{ // Just finished adding a round/magazine/whatever
if ((loadType == WTYPE_HAMMER_BREAK || loadType == WTYPE_HAMMER_BREAK_MULTI ||
loadType == WTYPE_BOLTACTION_BREECHLOAD || loadType == WTYPE_AUTO_BREECHLOAD)
&& character->ps.magazineAmmo[character->ps.weapon] < character->weaponSlot[character->ps.weapon].magazineSize)
{ // A weapon that loads one round at a time, and we have room for another
character->ps.magazineAmmo[character->ps.weapon]++; // FIXME - This could add more than one round?
// FIXME - remove a round from our ammo reserves
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].magInsertTime;
}
else if (loadType == WTYPE_HAMMER_BREAK || loadType == WTYPE_HAMMER_BREAK_MULTI ||
loadType == WTYPE_BOLTACTION_BREECHLOAD)
{ // A weapon that loads one at a time, but is already full and needs closing
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_CLOSING;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].weaponCloseTime;
}
else if (loadType == WTYPE_AUTO_BREECHLOAD && character->ps.chamberedAmmo[character->ps.weapon] < character->weaponSlot[character->ps.weapon].chamberedRounds)
{ // Needs to be cocked
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_COCKING;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].cockingTime;
}
else
{ // A weapon that fills up all in one go
character->ps.magazineAmmo[character->ps.weapon] = character->weaponSlot[character->ps.weapon].magazineSize; // FIXME - Add the amount of the mag we're holding in our hand, in case we're cancelling a reload
if (loadType == WTYPE_HAMMER_BREAKSIMULTANEOUS || loadType == WTYPE_HAMMER_BREAKSIMULTANEOUS_MULTI ||
loadType == WTYPE_BOLTACTION_CLIP || loadType == WTYPE_AUTO_CLIP || WTYPE_AUTO_BELT)
{ // Needs to be closed now the new ammo has been added
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_CLOSING;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].weaponCloseTime;
}
else if (character->ps.chamberedAmmo[character->ps.weapon] < character->weaponSlot[character->ps.weapon].chamberedRounds)
{ // Needs to be cocked immediately after adding the ammo, because there's an empty chamber
character->ps.magazineAmmo[character->ps.weapon] = character->weaponSlot[character->ps.weapon].magazineSize; // FIXME - Add the amount of the mag we're holding in our hand, in case we're cancelling a reload
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_COCKING;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].cockingTime;
}
else
{ // Doesn't need to be cocked or closed, ready to fire again
character->ps.magazineAmmo[character->ps.weapon] = character->weaponSlot[character->ps.weapon].magazineSize; // FIXME - Add the amount of the mag we're holding in our hand, in case we're cancelling a reload
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_READY;
character->ps.weaponState = WEAPONSTATE_READY;
}
}
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_OPENING)
{ // Just finished opening the weapon
if (loadType == WTYPE_HAMMER_BREAK || loadType == WTYPE_HAMMER_BREAKSIMULTANEOUS || 
loadType == WTYPE_HAMMER_BREAK_MULTI || loadType == WTYPE_HAMMER_BREAKSIMULTANEOUS_MULTI ||
loadType == WTYPE_AUTO_BELT)
{ // Old rounds have to be removed once the weapon is opened
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_REMOVING_OLD_AMMO;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].magPullTime;
}
else
{ // Can start adding rounds immediately after opening
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_ADDING_NEW_AMMO;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].magInsertTime;
}
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_CLOSING)
{ // Just finished closing the weapon
if (loadType == WTYPE_BOLTACTION_CLIP || loadType == WTYPE_BOLTACTION_BREECHLOAD)
{ // Closing the weapon cocks it, so we're ready to fire
character->ps.magazineAmmo[character->ps.weapon]--; // FIXME - could chamber !1 round?
character->ps.chamberedAmmo[character->ps.weapon]++; // FIXME - could chamber !1 round?
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_READY;
character->ps.weaponState = WEAPONSTATE_READY;
}
else
{ // Weapon needs to be cocked after closing
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_COCKING;
character->ps.weaponTime += character->weaponSlot[character->ps.weapon].cockingTime;
}
}
else if (character->ps.weaponLoadState[character->ps.weapon] == RELOADSTATE_COCKING)
{ // Just finished cocking the weapon, ready to fire
character->ps.magazineAmmo[character->ps.weapon]--; // FIXME - could chamber !1 round?
character->ps.chamberedAmmo[character->ps.weapon]++; // FIXME - could chamber !1 round?
character->ps.weaponLoadState[character->ps.weapon] = RELOADSTATE_READY;
character->ps.weaponState = WEAPONSTATE_READY;
}
}
}
}
 
void startWeaponReload(characterUnit_t *character)
{
completeWeapon_t *weapon = &character->weaponSlot[character->ps.weapon];
int *loadState = &character->ps.weaponLoadState[character->ps.weapon];
unsigned int *weaponTime = &character->ps.weaponTime;
 
if (character->ps.magazineAmmo[character->ps.weapon] >= weapon->magazineSize)
{ // Already a full mag, don't reload
return;
}
if (character->ps.shotsRemaining > 0)
{ // Don't reload if we're still trying to fire a burst
return;
}
// FIXME - Make sure we have ammo to put in our weapon
 
// Put us into the correct state for immediately after starting a reload
switch (character->weaponSlot[character->ps.weapon].loadType)
{
case WTYPE_MELEE:
return; // Melee shouldn't ever have to reload, right?
case WTYPE_HAMMER_BREAK:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_HAMMER_BREAKSIMULTANEOUS:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_HAMMER_BREAK_MULTI:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_HAMMER_BREAKSIMULTANEOUS_MULTI:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_BOLTACTION_CLIP:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_BOLTACTION_BREECHLOAD:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_BOLTACTION_MAGAZINE:
*loadState = RELOADSTATE_REMOVING_OLD_AMMO;
*weaponTime = GameTime + weapon->magPullTime;
break;
case WTYPE_AUTO_CLIP:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_AUTO_MAGAZINE:
*loadState = RELOADSTATE_REMOVING_OLD_AMMO;
*weaponTime = GameTime + weapon->magPullTime;
break;
case WTYPE_AUTO_MAGAZINE_SELFEJECTING:
*loadState = RELOADSTATE_ADDING_NEW_AMMO;
*weaponTime = GameTime + weapon->magInsertTime;
break;
case WTYPE_AUTO_BELT:
*loadState = RELOADSTATE_OPENING;
*weaponTime = GameTime + weapon->weaponOpenTime;
break;
case WTYPE_AUTO_BREECHLOAD:
*loadState = RELOADSTATE_ADDING_NEW_AMMO;
*weaponTime = GameTime + weapon->magInsertTime;
break;
default:
return;
}
 
character->ps.weaponState = WEAPONSTATE_RELOADING;
}

I'll let you know if it works. Edit: It didn't, but now it does.

Also the forum deleted all my indentations, but that just adds to the horror.

Advertisement
You have too many comments in the code... :-)

That's true, it could be far more horrific.

It's cocking time!

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

I've been smirking all day.

Ever think of creating more local variable to simplify your logics for readability???

WEAP = character->ps.weapon

WLS = character->ps.weaponLoadState[WEAP];

MA = character->ps.magazineAmmo[WEAP] ;

CA = character->ps.chamberedAmmo[WEAP];

etc.. you looked like you started that with loadType ...

at minimum you aught to be able to simplify down the character->ps to a pointer and use WEAP everywhere

Half the horror is its verboseoscopy

--------------------------------------------[size="1"]Ratings are Opinion, not Fact


verboseoscopy

My new favourite phrase.

It sounds almost as unpleasant as a colonoscopy (unnecessary over-use of semi-colons).

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]


verboseoscopy

My new favourite phrase.

It sounds almost as unpleasant as a colonoscopy (unnecessary over-use of semi-colons).

The code could really use a verbosectomy.

This topic is closed to new replies.

Advertisement