void NPC_SetAnim(gentity_t *ent,int setAnimParts,int anim,int setAnimFlags) { // FIXME : once torsoAnim and legsAnim are in the same structure for NCP and Players // rename PM_SETAnimFinal to PM_SetAnim and have both NCP and Players call PM_SetAnim if(ent->client) {//Players, NPCs if (setAnimFlags&SETANIM_FLAG_OVERRIDE) { if (setAnimParts & SETANIM_TORSO) { if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ent->client->ps.torsoAnim & ~ANIM_TOGGLEBIT ) != anim ) { PM_SetTorsoAnimTimer( ent, &ent->client->ps.torsoAnimTimer, 0 ); } } if (setAnimParts & SETANIM_LEGS) { if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ent->client->ps.legsAnim & ~ANIM_TOGGLEBIT ) != anim ) { PM_SetLegsAnimTimer( ent, &ent->client->ps.legsAnimTimer, 0 ); } } } PM_SetAnimFinal(&ent->client->ps.torsoAnim,&ent->client->ps.legsAnim,setAnimParts,anim,setAnimFlags, &ent->client->ps.torsoAnimTimer,&ent->client->ps.legsAnimTimer,ent); } else {//bodies, etc. if (setAnimFlags&SETANIM_FLAG_OVERRIDE) { if (setAnimParts & SETANIM_TORSO) { if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ent->s.torsoAnim & ~ANIM_TOGGLEBIT ) != anim ) { PM_SetTorsoAnimTimer( ent, &ent->s.torsoAnimTimer, 0 ); } } if (setAnimParts & SETANIM_LEGS) { if( (setAnimFlags & SETANIM_FLAG_RESTART) || (ent->s.legsAnim & ~ANIM_TOGGLEBIT ) != anim ) { PM_SetLegsAnimTimer( ent, &ent->s.legsAnimTimer, 0 ); } } } PM_SetAnimFinal(&ent->s.torsoAnim,&ent->s.legsAnim,setAnimParts,anim,setAnimFlags, &ent->s.torsoAnimTimer,&ent->s.legsAnimTimer,ent); } }
// Imported from single-player, this function is mainly intended to make porting from SP easier. void PM_SetAnim(int setAnimParts, animNumber_t anim, int setAnimFlags, int blendTime) { assert( anim < MAX_TOTALANIMATIONS); assert( bgGlobalAnimations[anim].firstFrame != 0 || bgGlobalAnimations[anim].numFrames != 0); if (BG_InSpecialJump(anim)) { setAnimFlags |= SETANIM_FLAG_RESTART; } if (BG_InRoll(pm->ps, pm->ps->legsAnim)) { //never interrupt a roll return; } if (setAnimFlags&SETANIM_FLAG_OVERRIDE) { if (setAnimParts & SETANIM_TORSO) { if( (setAnimFlags & SETANIM_FLAG_RESTART) || (pm->ps->torsoAnim & ~ANIM_TOGGLEBIT ) != anim ) { PM_SetTorsoAnimTimer(0); } } if (setAnimParts & SETANIM_LEGS) { if( (setAnimFlags & SETANIM_FLAG_RESTART) || (pm->ps->legsAnim & ~ANIM_TOGGLEBIT ) != anim ) { PM_SetLegsAnimTimer(0); } } } PM_SetAnimFinal(setAnimParts, anim, setAnimFlags, blendTime); }
void NPC_CheckAttackHold(void) { vec3_t vec; // If they don't have an enemy they shouldn't hold their attack anim. if ( !NPC->enemy ) { NPCInfo->attackHoldTime = 0; return; } if ( ( NPC->client->ps.weapon == WP_BORG_ASSIMILATOR ) || ( NPC->client->ps.weapon == WP_BORG_DRILL ) ) {//FIXME: don't keep holding this if can't hit enemy? // If they don't have shields ( been disabled) they shouldn't hold their attack anim. if ( !(NPC->NPC->aiFlags & NPCAI_SHIELDS) ) { NPCInfo->attackHoldTime = 0; return; } VectorSubtract(NPC->enemy->currentOrigin, NPC->currentOrigin, vec); if( VectorLengthSquared(vec) > NPC_MaxDistSquaredForWeapon() ) { NPCInfo->attackHoldTime = 0; PM_SetTorsoAnimTimer(NPC, &NPC->client->ps.torsoAnimTimer, 0); } else if( NPCInfo->attackHoldTime && NPCInfo->attackHoldTime > level.time ) { ucmd.buttons |= BUTTON_ATTACK; } else if ( ( NPCInfo->attackHold ) && ( ucmd.buttons & BUTTON_ATTACK ) ) { NPCInfo->attackHoldTime = level.time + NPCInfo->attackHold; PM_SetTorsoAnimTimer(NPC, &NPC->client->ps.torsoAnimTimer, NPCInfo->attackHold); } else { NPCInfo->attackHoldTime = 0; PM_SetTorsoAnimTimer(NPC, &NPC->client->ps.torsoAnimTimer, 0); } } else {//everyone else...? FIXME: need to tie this into AI somehow? VectorSubtract(NPC->enemy->currentOrigin, NPC->currentOrigin, vec); if( VectorLengthSquared(vec) > NPC_MaxDistSquaredForWeapon() ) { NPCInfo->attackHoldTime = 0; } else if( NPCInfo->attackHoldTime && NPCInfo->attackHoldTime > level.time ) { ucmd.buttons |= BUTTON_ATTACK; } else if ( ( NPCInfo->attackHold ) && ( ucmd.buttons & BUTTON_ATTACK ) ) { NPCInfo->attackHoldTime = level.time + NPCInfo->attackHold; } else { NPCInfo->attackHoldTime = 0; } } }