// Function: A_RecyclePowers
//
// Description: Take all player's powers, and swap 'em.
//
// var1 = unused
// var2 = unused
//
void A_RecyclePowers(mobj_t *actor)
{
INT32 i, j, k, numplayers = 0;
#ifdef WEIGHTEDRECYCLER
UINT8 beneficiary = 255;
#endif
UINT8 playerslist[MAXPLAYERS];
UINT8 postscramble[MAXPLAYERS];
UINT16 powers[MAXPLAYERS][NUMPOWERS];
INT32 weapons[MAXPLAYERS];
INT32 weaponheld[MAXPLAYERS];
#ifdef HAVE_BLUA
if (LUA_CallAction("A_RecyclePowers", actor))
return;
#endif
#if !defined(WEIGHTEDRECYCLER) && !defined(HAVE_BLUA)
// actor is used in all scenarios but this one, funny enough
(void)actor;
#endif
if (!multiplayer)
{
S_StartSound(actor, sfx_lose);
return;
}
numplayers = 0;
// Count the number of players in the game
for (i = 0, j = 0; i < MAXPLAYERS; i++)
{
if (playeringame[i] && players[i].mo && players[i].mo->health > 0 && players[i].playerstate == PST_LIVE
&& !players[i].exiting && !((netgame || multiplayer) && players[i].spectator))
{
#ifndef WEIGHTEDRECYCLER
if (players[i].powers[pw_super])
continue; // Ignore super players
#endif
numplayers++;
postscramble[j] = playerslist[j] = (UINT8)i;
#ifdef WEIGHTEDRECYCLER
// The guy who started the recycle gets the best result
if (actor && actor->target && actor->target->player && &players[i] == actor->target->player)
beneficiary = (UINT8)i;
#endif
// Save powers
for (k = 0; k < NUMPOWERS; k++)
powers[i][k] = players[i].powers[k];
//1.1: ring weapons too
weapons[i] = players[i].ringweapons;
weaponheld[i] = players[i].currentweapon;
j++;
}
}
if (numplayers <= 1)
{
S_StartSound(actor, sfx_lose);
return; //nobody to touch!
}
//shuffle the post scramble list, whee!
// hardcoded 0-1 to 1-0 for two players
if (numplayers == 2)
{
postscramble[0] = playerslist[1];
postscramble[1] = playerslist[0];
}
else
for (j = 0; j < numplayers; j++)
{
UINT8 tempint;
i = j + ((P_RandomByte() + leveltime) % (numplayers - j));
tempint = postscramble[j];
postscramble[j] = postscramble[i];
postscramble[i] = tempint;
}
#ifdef WEIGHTEDRECYCLER
//the joys of qsort...
if (beneficiary != 255) {
qsort(playerslist, numplayers, sizeof(UINT8), P_RecycleCompare);
// now, make sure the benificiary is in the best slot
// swap out whatever poor sap was going to get the best items
for (i = 0; i < numplayers; i++)
{
if (postscramble[i] == beneficiary)
{
postscramble[i] = postscramble[0];
postscramble[0] = beneficiary;
break;
}
}
}
#endif
// now assign!
for (i = 0; i < numplayers; i++)
{
UINT8 send_pl = playerslist[i];
UINT8 recv_pl = postscramble[i];
// debugF
CONS_Debug(DBG_GAMELOGIC, "sending player %hu's items to %hu\n", (UINT16)send_pl, (UINT16)recv_pl);
for (j = 0; j < NUMPOWERS; j++)
{
if (j == pw_flashing || j == pw_underwater || j == pw_spacetime || j == pw_carry
|| j == pw_tailsfly || j == pw_extralife || j == pw_nocontrol || j == pw_super)
continue;
players[recv_pl].powers[j] = powers[send_pl][j];
}
//1.1: weapon rings too
players[recv_pl].ringweapons = weapons[send_pl];
players[recv_pl].currentweapon = weaponheld[send_pl];
if (((players[recv_pl].powers[pw_shield] & SH_NOSTACK) == SH_PINK) && (players[recv_pl].revitem == MT_LHRT || players[recv_pl].spinitem == MT_LHRT || players[recv_pl].thokitem == MT_LHRT)) // Healers can't keep their buff.
players[recv_pl].powers[pw_shield] &= SH_STACK;
P_SpawnShieldOrb(&players[recv_pl]);
if (P_IsLocalPlayer(&players[recv_pl]))
P_RestoreMusic(&players[recv_pl]);
P_FlashPal(&players[recv_pl], PAL_RECYCLE, 10);
}
S_StartSound(NULL, sfx_gravch); //heh, the sound effect I used is already in
}