Ejemplo n.º 1
0
//
// A_CounterSwitch
//
// This powerful codepointer can branch to one of N states
// depending on the value of the indicated counter, and it
// remains totally safe at all times. If the entire indicated
// frame set is not valid, no actions will be taken.
//
// args[0] : counter # to use
// args[1] : DeHackEd number of first frame in consecutive set
// args[2] : number of frames in consecutive set
//
void A_CounterSwitch(Mobj *mo)
{
   int cnum, startstate, numstates;
   int *counter;

   cnum       = E_ArgAsInt(mo->state->args,        0, 0);
   startstate = E_ArgAsStateNumNI(mo->state->args, 1, mo);
   numstates  = E_ArgAsInt(mo->state->args,        2, 0) - 1;

   // get counter
   if(cnum < 0 || cnum >= NUMMOBJCOUNTERS)
      return; // invalid

   counter = &(mo->counters[cnum]);

   // verify startstate
   if(startstate < 0)
      return;

   // verify last state is < NUMSTATES
   if(startstate + numstates >= NUMSTATES)
      return;

   // verify counter is in range
   if(*counter < 0 || *counter > numstates)
      return;

   // jump!
   P_SetMobjState(mo, startstate + *counter);
}
Ejemplo n.º 2
0
//
// A_CounterJump
//
// Parameterized codepointer for branching based on comparisons
// against a thing's counter values.
//
// args[0] : state number
// args[1] : comparison type
// args[2] : immediate value OR counter number
// args[3] : counter # to use
//
void A_CounterJump(Mobj *mo)
{
   bool branch = false;
   int statenum, checktype, value, cnum;
   int *counter;

   statenum  = E_ArgAsStateNumNI(mo->state->args, 0, mo);
   checktype = E_ArgAsKwd(mo->state->args, 1, &cpckwds, 0);
   value     = E_ArgAsInt(mo->state->args, 2, 0);
   cnum      = E_ArgAsInt(mo->state->args, 3, 0);
   
   // validate state
   if(statenum < 0)
      return;

   if(cnum < 0 || cnum >= NUMMOBJCOUNTERS)
      return; // invalid

   counter = &(mo->counters[cnum]);

   // 08/02/04:
   // support getting check value from a counter
   // if checktype is greater than the last immediate operator,
   // then the comparison value is actually a counter number

   if(checktype >= CPC_NUMIMMEDIATE)
   {
      // turn it into the corresponding immediate operation
      checktype -= CPC_NUMIMMEDIATE;

      if(value < 0 || value >= NUMMOBJCOUNTERS)
         return; // invalid counter number

      value = mo->counters[value];
   }

   switch(checktype)
   {
   case CPC_LESS:
      branch = (*counter < value);  break;
   case CPC_LESSOREQUAL:
      branch = (*counter <= value); break;
   case CPC_GREATER:
      branch = (*counter > value);  break;
   case CPC_GREATEROREQUAL:
      branch = (*counter >= value); break;
   case CPC_EQUAL:
      branch = (*counter == value); break;
   case CPC_NOTEQUAL:
      branch = (*counter != value); break;
   case CPC_BITWISEAND:
      branch = !!(*counter & value);  break;
   default:
      break;
   }

   if(branch)
      P_SetMobjState(mo, statenum);
}
Ejemplo n.º 3
0
//
// A_SetCounter
//
// Sets the value of the indicated counter variable for the thing.
// Can perform numerous operations -- this is more like a virtual
// machine than a codepointer ;)
//
// args[0] : counter # to set
// args[1] : value to utilize
// args[2] : operation to perform
//
void A_SetCounter(Mobj *mo)
{
   int cnum, value, specialop;
   int *counter;

   cnum      = E_ArgAsInt(mo->state->args, 0, 0);
   value     = E_ArgAsInt(mo->state->args, 1, 0);
   specialop = E_ArgAsKwd(mo->state->args, 2, &cpsetkwds, 0);

   if(cnum < 0 || cnum >= NUMMOBJCOUNTERS)
      return; // invalid

   counter = &(mo->counters[cnum]);

   switch(specialop)
   {
   case CPOP_ASSIGN:
      *counter = value; break;
   case CPOP_ADD:
      *counter += value; break;
   case CPOP_SUB:
      *counter -= value; break;
   case CPOP_MUL:
      *counter *= value; break;
   case CPOP_DIV:
      if(value) // don't divide by zero
         *counter /= value;
      break;
   case CPOP_MOD:
      if(value > 0) // only allow modulus by positive values
         *counter %= value;
      break;
   case CPOP_AND:
      *counter &= value; break;
   case CPOP_ANDNOT:
      *counter &= ~value; break; // compound and-not operation
   case CPOP_OR:
      *counter |= value; break;
   case CPOP_XOR:
      *counter ^= value; break;
   case CPOP_RND:
      *counter = P_Random(pr_setcounter); break;
   case CPOP_RNDMOD:
      if(value > 0)
         *counter = P_Random(pr_setcounter) % value;
      break;
   case CPOP_SHIFTLEFT:
      *counter <<= value; break;
   case CPOP_SHIFTRIGHT:
      *counter >>= value; break;
   default:
      break;
   }
}
Ejemplo n.º 4
0
//
// A_SargAttack12
//
// DOOM 1.2 Demon attack
// haleyjd 07/29/14
//
void A_SargAttack12(actionargs_t *actionargs)
{
   Mobj *actor = actionargs->actor;
   int damage, mod, mul;

   if(!actor->target)
      return;

   mod = E_ArgAsInt(actionargs->args, 0, 10);
   mul = E_ArgAsInt(actionargs->args, 1,  4);

   A_FaceTarget(actionargs);
   damage = ((P_Random(pr_sargattack) % mod) + 1) * mul;
   P_LineAttack(actor, actor->angle, MELEERANGE, 0, damage);
}
Ejemplo n.º 5
0
//
// A_WeaponCtrSwitch
//
// This powerful codepointer can branch to one of N states
// depending on the value of the indicated counter, and it
// remains totally safe at all times. If the entire indicated
// frame set is not valid, no actions will be taken.
//
// args[0] : counter # to use
// args[1] : DeHackEd number of first frame in consecutive set
// args[2] : number of frames in consecutive set
// args[3] : psprite to affect (weapon or flash)
//
void A_WeaponCtrSwitch(Mobj *mo)
{
   int cnum, startstate, numstates, psprnum;
   int *counter;
   player_t *player;
   pspdef_t *pspr;

   if(!(player = mo->player))
      return;

   pspr = &(player->psprites[player->curpsprite]);

   cnum       = E_ArgAsInt(pspr->state->args, 0, 0);
   startstate = E_ArgAsStateNumNI(pspr->state->args, 1, NULL);
   numstates  = E_ArgAsInt(pspr->state->args, 2, 0) - 1;
   psprnum    = E_ArgAsKwd(pspr->state->args, 3, &psprkwds, 0);

   // validate psprite number
   if(psprnum < 0 || psprnum >= NUMPSPRITES)
      return;

   // get counter
   switch(cnum)
   {
   case 0:
   case 1:
   case 2:
      counter = &(player->weaponctrs[player->readyweapon][cnum]); 
      break;
   default:
      return;
   }

   // verify startstate
   if(startstate < 0)
      return;

   // verify last state is < NUMSTATES
   if(startstate + numstates >= NUMSTATES)
      return;

   // verify counter is in range
   if(*counter < 0 || *counter > numstates)
      return;

   // jump!
   P_SetPsprite(player, psprnum, startstate + *counter);
}
Ejemplo n.º 6
0
//
// A_CopyCounter
//
// Copies the value of one counter into another.
//
// args[0] : source counter #
// args[1] : destination counter #
//
void A_CopyCounter(Mobj *mo)
{
   int cnum1, cnum2;
   int *src, *dest;

   cnum1 = E_ArgAsInt(mo->state->args, 0, 0);
   cnum2 = E_ArgAsInt(mo->state->args, 1, 0);

   if(cnum1 < 0 || cnum1 >= NUMMOBJCOUNTERS)
      return; // invalid

   src = &(mo->counters[cnum1]);

   if(cnum2 < 0 || cnum2 >= NUMMOBJCOUNTERS)
      return; // invalid

   dest = &(mo->counters[cnum2]);

   *dest = *src;
}
Ejemplo n.º 7
0
//
// A_SubTics
//
// Note: was A_DelayGib in Hexen
// Parameters:
// * args[0] : mode select (0 = random amt, 1 = use args[1])
// * args[1] : if mode == 0, shift amt; if mode == 1, amount to subtract
//
void A_SubTics(Mobj *actor)
{
   int mode = E_ArgAsInt(actor->state->args, 0, 0);
   int amt  = E_ArgAsInt(actor->state->args, 1, 0);

   switch(mode)
   {
   case 0:
      actor->tics -= P_Random(pr_subtics) >> amt;
      break;
   case 1:
      actor->tics -= amt;
      break;
   default:
      break;
   }

   // cannot set tics to zero, to avoid state cycles.
   if(actor->tics <= 0)
      actor->tics = 1;
}
Ejemplo n.º 8
0
//
// A_HealthJump
//
// Parameterized codepointer for branching based on comparisons
// against a thing's health.
//
// args[0] : state number
// args[1] : comparison type
// args[2] : health value OR counter number
//
void A_HealthJump(Mobj *mo)
{
   bool branch = false;   
   int statenum, checktype, checkhealth;

   statenum    = E_ArgAsStateNumNI(mo->state->args, 0, mo);
   checktype   = E_ArgAsKwd(mo->state->args, 1, &cpckwds, 0);
   checkhealth = E_ArgAsInt(mo->state->args, 2, 0);

   // validate state
   if(statenum < 0)
      return;
   
   // 08/02/04:
   // support getting check value from a counter
   // if checktype is greater than the last immediate operator,
   // then the checkhealth value is actually a counter number

   if(checktype >= CPC_NUMIMMEDIATE)
   {
      // turn it into the corresponding immediate operation
      checktype -= CPC_NUMIMMEDIATE;

      if(checkhealth < 0 || checkhealth >= NUMMOBJCOUNTERS)
         return; // invalid counter number

      checkhealth = mo->counters[checkhealth];
   }

   switch(checktype)
   {
   case CPC_LESS:
      branch = (mo->health < checkhealth);  break;
   case CPC_LESSOREQUAL:
      branch = (mo->health <= checkhealth); break;
   case CPC_GREATER:
      branch = (mo->health > checkhealth);  break;
   case CPC_GREATEROREQUAL:
      branch = (mo->health >= checkhealth); break;
   case CPC_EQUAL:
      branch = (mo->health == checkhealth); break;
   case CPC_NOTEQUAL:
      branch = (mo->health != checkhealth); break;
   case CPC_BITWISEAND:
      branch = !!(mo->health & checkhealth);  break;
   default:
      break;
   }

   if(branch)
      P_SetMobjState(mo, statenum);
}
Ejemplo n.º 9
0
//
// A_WeaponCopyCtr
//
// Copies the value of one counter into another.
//
// args[0] : source counter #
// args[1] : destination counter #
//
void A_WeaponCopyCtr(Mobj *mo)
{
   int cnum1, cnum2;
   int *src, *dest;
   player_t *player;
   pspdef_t *pspr;

   if(!(player = mo->player))
      return;

   pspr  = &(player->psprites[player->curpsprite]);

   cnum1 = E_ArgAsInt(pspr->state->args, 0, 0);
   cnum2 = E_ArgAsInt(pspr->state->args, 1, 0);

   switch(cnum1)
   {
   case 0:
   case 1:
   case 2:
      src = &(player->weaponctrs[player->readyweapon][cnum1]); break;
   default:
      return;
   }

   switch(cnum2)
   {
   case 0:
   case 1:
   case 2:
      dest = &(player->weaponctrs[player->readyweapon][cnum2]); break;
   default:
      return;
   }

   *dest = *src;
}
Ejemplo n.º 10
0
//
// A_LowerFloorClip
//
// Note: was A_SerpentLowerHump in Hexen
// Parameters:
// * args[0] == amount to increase floorclip in eighths of a unit
//
void A_LowerFloorClip(Mobj *actor)
{
   fixed_t amt = E_ArgAsInt(actor->state->args, 0, 0) * FRACUNIT / 8;

   actor->floorclip += amt;
}
Ejemplo n.º 11
0
//
// A_WeaponCtrOp
//
// Sets the value of the indicated counter variable for the weapon
// using two (possibly the same) counters as operands.
//
// args[0] : counter operand #1
// args[1] : counter operand #2
// args[2] : counter destination
// args[3] : operation to perform
//
void A_WeaponCtrOp(Mobj *mo)
{
   player_t *player;
   pspdef_t *pspr;
   int c_oper1_num;
   int c_oper2_num;
   int c_dest_num;
   int specialop;

   int *c_oper1, *c_oper2, *c_dest;

   if(!(player = mo->player))
      return;

   pspr = &(player->psprites[player->curpsprite]);

   c_oper1_num = E_ArgAsInt(pspr->state->args, 0, 0);
   c_oper2_num = E_ArgAsInt(pspr->state->args, 1, 0);
   c_dest_num  = E_ArgAsInt(pspr->state->args, 2, 0);
   specialop   = E_ArgAsKwd(pspr->state->args, 3, &weapctropkwds, 0);

   switch(c_oper1_num)
   {
   case 0:
   case 1:
   case 2:
      c_oper1 = &(player->weaponctrs[player->readyweapon][c_oper1_num]);
      break;
   default:
      return;
   }

   switch(c_oper2_num)
   {
   case 0:
   case 1:
   case 2:
      c_oper2 = &(player->weaponctrs[player->readyweapon][c_oper2_num]);
      break;
   default:
      return;
   }

   switch(c_dest_num)
   {
   case 0:
   case 1:
   case 2:
      c_dest = &(player->weaponctrs[player->readyweapon][c_dest_num]); break;
   default:
      return;
   }

   switch(specialop)
   {
   case CPOP_ADD:
      *c_dest = *c_oper1 + *c_oper2; break;
   case CPOP_SUB:
      *c_dest = *c_oper1 - *c_oper2; break;
   case CPOP_MUL:
      *c_dest = *c_oper1 * *c_oper2; break;
   case CPOP_DIV:
      if(c_oper2) // don't divide by zero
         *c_dest = *c_oper1 / *c_oper2;
      break;
   case CPOP_MOD:
      if(*c_oper2 > 0) // only allow modulus by positive values
         *c_dest = *c_oper1 % *c_oper2;
      break;
   case CPOP_AND:
      *c_dest = *c_oper1 & *c_oper2; break;
   case CPOP_OR:
      *c_dest = *c_oper1 | *c_oper2; break;
   case CPOP_XOR:
      *c_dest = *c_oper1 ^ *c_oper2; break;
   case CPOP_DAMAGE:
      // do a HITDICE-style calculation
      if(*c_oper2 > 0) // the modulus must be positive
         *c_dest = *c_oper1 * ((P_Random(pr_weapsetctr) % *c_oper2) + 1);
      break;
   case CPOP_SHIFTLEFT:
      *c_dest = *c_oper1 << *c_oper2; break;
   case CPOP_SHIFTRIGHT:
      *c_dest = *c_oper1 >> *c_oper2; break;

      // unary operations (c_oper2 is unused for these)
   case CPOP_ABS:
      *c_dest = abs(*c_oper1); break;
   case CPOP_NEGATE:
      *c_dest = -(*c_oper1); break;
   case CPOP_NOT:
      *c_dest = !(*c_oper1); break;
   case CPOP_INVERT:
      *c_dest = ~(*c_oper1); break;
   default:
      break;
   }
}
Ejemplo n.º 12
0
//
// A_WeaponSetCtr
//
// Sets the value of the indicated counter variable for the thing.
// Can perform numerous operations -- this is more like a virtual
// machine than a codepointer ;)
//
// args[0] : counter # to set
// args[1] : value to utilize
// args[2] : operation to perform
//
void A_WeaponSetCtr(Mobj *mo)
{
   int cnum;
   int value;
   int specialop;
   int *counter;
   player_t *player;
   pspdef_t *pspr;

   if(!(player = mo->player))
      return;

   pspr = &(player->psprites[player->curpsprite]);

   cnum      = E_ArgAsInt(pspr->state->args, 0, 0);
   value     = E_ArgAsInt(pspr->state->args, 1, 0);
   specialop = E_ArgAsKwd(pspr->state->args, 2, &weapsetkwds, 0);

   switch(cnum)
   {
   case 0:
   case 1:
   case 2:
      counter = &(player->weaponctrs[player->readyweapon][cnum]); break;
   default:
      return;
   }

   switch(specialop)
   {
   case CPOP_ASSIGN:
      *counter = value; break;
   case CPOP_ADD:
      *counter += value; break;
   case CPOP_SUB:
      *counter -= value; break;
   case CPOP_MUL:
      *counter *= value; break;
   case CPOP_DIV:
      if(value) // don't divide by zero
         *counter /= value;
      break;
   case CPOP_MOD:
      if(value > 0) // only allow modulus by positive values
         *counter %= value;
      break;
   case CPOP_AND:
      *counter &= value; break;
   case CPOP_ANDNOT:
      *counter &= ~value; break; // compound and-not operation
   case CPOP_OR:
      *counter |= value; break;
   case CPOP_XOR:
      *counter ^= value; break;
   case CPOP_RND:
      *counter = P_Random(pr_weapsetctr); break;
   case CPOP_RNDMOD:
      if(value > 0)
         *counter = P_Random(pr_weapsetctr) % value; break;
   case CPOP_SHIFTLEFT:
      *counter <<= value; break;
   case CPOP_SHIFTRIGHT:
      *counter >>= value; break;
   default:
      break;
   }
}
Ejemplo n.º 13
0
//
// A_WeaponCtrJump
//
// Parameterized codepointer for branching based on comparisons
// against a weapon's counter values.
//
// args[0] : state number
// args[1] : comparison type
// args[2] : immediate value OR counter number
// args[3] : counter # to use
// args[4] : psprite to affect (weapon or flash)
//
void A_WeaponCtrJump(Mobj *mo)
{
   bool branch = false;
   int statenum, checktype, cnum, psprnum;
   int value, *counter;
   player_t *player;
   pspdef_t *pspr;

   if(!(player = mo->player))
      return;

   pspr = &(player->psprites[player->curpsprite]);

   statenum  = E_ArgAsStateNumNI(pspr->state->args, 0, NULL);
   checktype = E_ArgAsKwd(pspr->state->args, 1, &weapctrkwds, 0);
   value     = E_ArgAsInt(pspr->state->args, 2, 0);
   cnum      = E_ArgAsInt(pspr->state->args, 3, 0);
   psprnum   = E_ArgAsKwd(pspr->state->args, 4, &psprkwds, 0);
   
   // validate state
   if(statenum < 0)
      return;

   // validate psprite number
   if(psprnum < 0 || psprnum >= NUMPSPRITES)
      return;

   switch(cnum)
   {
   case 0:
   case 1:
   case 2:
      counter = &(player->weaponctrs[player->readyweapon][cnum]); break;
   default:
      return;
   }

   // 08/02/04:
   // support getting check value from a counter
   // if checktype is greater than the last immediate operator,
   // then the comparison value is actually a counter number

   if(checktype >= CPC_NUMIMMEDIATE)
   {
      // turn it into the corresponding immediate operation
      checktype -= CPC_NUMIMMEDIATE;

      switch(value)
      {
      case 0:
      case 1:
      case 2:
         value = player->weaponctrs[player->readyweapon][value];
         break;
      default:
         return; // invalid counter number
      }
   }

   switch(checktype)
   {
   case CPC_LESS:
      branch = (*counter < value); break;
   case CPC_LESSOREQUAL:
      branch = (*counter <= value); break;
   case CPC_GREATER:
      branch = (*counter > value); break;
   case CPC_GREATEROREQUAL:
      branch = (*counter >= value); break;
   case CPC_EQUAL:
      branch = (*counter == value); break;
   case CPC_NOTEQUAL:
      branch = (*counter != value); break;
   case CPC_BITWISEAND:
      branch = !!(*counter & value); break;
   default:
      break;
   }

   if(branch)
      P_SetPsprite(player, psprnum, statenum);
      
}
Ejemplo n.º 14
0
//
// A_CounterOp
//
// Sets the value of the indicated counter variable for the thing
// using two (possibly the same) counters as operands.
//
// args[0] : counter operand #1
// args[1] : counter operand #2
// args[2] : counter destination
// args[3] : operation to perform
//
void A_CounterOp(Mobj *mo)
{
   int c_oper1_num, c_oper2_num, c_dest_num, specialop;
   int *c_oper1, *c_oper2, *c_dest;

   c_oper1_num = E_ArgAsInt(mo->state->args, 0, 0);
   c_oper2_num = E_ArgAsInt(mo->state->args, 1, 0);
   c_dest_num  = E_ArgAsInt(mo->state->args, 2, 0);   
   specialop   = E_ArgAsKwd(mo->state->args, 3, &cpopkwds, 0);

   if(c_oper1_num < 0 || c_oper1_num >= NUMMOBJCOUNTERS)
      return; // invalid

   c_oper1 = &(mo->counters[c_oper1_num]);

   if(c_oper2_num < 0 || c_oper2_num >= NUMMOBJCOUNTERS)
      return; // invalid

   c_oper2 = &(mo->counters[c_oper2_num]);

   if(c_dest_num < 0 || c_dest_num >= NUMMOBJCOUNTERS)
      return; // invalid

   c_dest = &(mo->counters[c_dest_num]);

   switch(specialop)
   {
   case CPOP_ADD:
      *c_dest = *c_oper1 + *c_oper2; break;
   case CPOP_SUB:
      *c_dest = *c_oper1 - *c_oper2; break;
   case CPOP_MUL:
      *c_dest = *c_oper1 * *c_oper2; break;
   case CPOP_DIV:
      if(c_oper2) // don't divide by zero
         *c_dest = *c_oper1 / *c_oper2;
      break;
   case CPOP_MOD:
      if(*c_oper2 > 0) // only allow modulus by positive values
         *c_dest = *c_oper1 % *c_oper2;
      break;
   case CPOP_AND:
      *c_dest = *c_oper1 & *c_oper2; break;
   case CPOP_OR:
      *c_dest = *c_oper1 | *c_oper2; break;
   case CPOP_XOR:
      *c_dest = *c_oper1 ^ *c_oper2; break;
   case CPOP_DAMAGE:
      // do a HITDICE-style calculation
      if(*c_oper2 > 0) // the modulus must be positive
         *c_dest = *c_oper1 * ((P_Random(pr_setcounter) % *c_oper2) + 1);
      break;
   case CPOP_SHIFTLEFT:
      *c_dest = *c_oper1 << *c_oper2; break;
   case CPOP_SHIFTRIGHT:
      *c_dest = *c_oper1 >> *c_oper2; break;

      // unary operations (c_oper2 is unused for these)
   case CPOP_ABS:
      *c_dest = abs(*c_oper1); break;
   case CPOP_NEGATE:
      *c_dest = -(*c_oper1); break;
   case CPOP_NOT:
      *c_dest = !(*c_oper1); break;
   case CPOP_INVERT:
      *c_dest = ~(*c_oper1); break;
   default:
      break;
   }
}