void CActorInstance::InputNormalAttackCommand(float fDirRot) { if (!__CanInputNormalAttackCommand()) return; m_fAtkDirRot=fDirRot; NormalAttack(m_fAtkDirRot); }
/* 정인호. 11/20 광역 공격 처리. 현재 로직은 PlayScene의 모든 Enemy를 리스트로 돌면서 지정된 SplashRange내부에 있는 적들은 모두 데미지를 받도록 처리함 */ void CCharacter::SplashAttack( NNPoint splashPoint, clock_t currentTime ) { switch (m_Identity) { case ZOMBIE: for (const auto& enemy : *CPlayScene::GetInstance()->GetPoliceList()) { if(this->m_SplashAttackRange >= splashPoint.GetDistance(enemy->GetPosition())) { NormalAttack(enemy, currentTime); } } break; case POLICE: for (const auto& enemy : *CPlayScene::GetInstance()->GetZombieList()) { if(this->m_SplashAttackRange >= splashPoint.GetDistance(enemy->GetPosition())) { NormalAttack(enemy, currentTime); } } break; default: break; } }
void CCharacter::AttackEnemy( clock_t currentTime ) { //splash속성이 true인 몬스터면 splash어택 if(m_SplashAttack) { SplashAttack(m_AttackTarget->GetPosition(), currentTime); } else { // 아니면 normal attack NormalAttack(m_AttackTarget, currentTime); } // 자폭 공격 캐릭터일 경우 hp를 0으로.. if (m_SuicideBomber) { m_HealthPoint = 0.0f; } // set the last attack time m_LastAttackTime = currentTime; }
// 버서크 상태의 처리 void Berserk( int num_shot, // 아군의 샷의 수 int num_enemy, // 적기의 갯수 int num_bullet // 탄(적기의 탄)의 갯수 ) { static STATE_TYPE state=NORMAL; // 메인 캐릭터의 상태(처음에는 보통 상태) static int energy=0; // 에너지 static int berserk_energy=100; // 버서크 상태가 되기 위해 // 필요한 에너지 static int time; // 버서크 효과의 잔여시간 // 메인 캐릭터의 상태에 따라 분기 switch (state) { // 보통 상태 case NORMAL: // 보통 공격: // 구체적인 처리는 NormalAttack 함수에서 수행하기로 함. NormalAttack(); // 탄이나 적기와 접촉 판정: // 부딪히면 피해를 받음. // 판정이나 결과의 구체적인 처리는 HitEnemy, // HitBullet, Miss 함수에서 각각 수행하기로 함. for (int i=0; i<num_enemy; i++) if (HitEnemy(i)) Miss(); for (int i=0; i<num_bullet; i++) if (HitBullet(i)) Miss(); // 아군 캐릭터가 쏜 샷과 접촉 판정: // 에너지를 모음. // 판정이나 결과의 구체적인 처리는 HitShot, // DeleteShot 함수에서 각각 수행하기로 함. for (int i=0; i<num_shot; i++) { if (HitShot(i)) { energy++; DeleteShot(i); } } // 에너지 양 판단: // 에너지가 충분히 모였으면 // 버서크 상태로 이동함. // 에너지는 시간이 지남에 따라 저절로 감소됨. if (energy>=berserk_energy) { state=BERSERK; time=300; } else { energy--; } break; // 버서크 상태 case BERSERK: // 특수 공격: // 구체적인 처리는 SpecialAttack 함수에서 수행하기로 함. SpecialAttack(); // 적기나 탄과 접촉 판정: // 적기에는 피해를 주고 탄은 제거함. // 결과의 구체적인 처리는 DamageEnemy, // DeleteBullet 함수에서 각각 수행하기로 함. for (int i=0; i<num_enemy; i++) if (HitEnemy(i)) DamageEnemy(i); for (int i=0; i<num_bullet; i++) if (HitBullet(i)) DeleteBullet(i); // 남은 시간이 다 되었다면 약한 상태로 이동함. time--; if (time<=0) { state=WEAK; time=200; } break; // 약한 상태 case WEAK: // 적기나 탄과 접촉 판정: // 맞으면 피해를 받음. for (int i=0; i<num_enemy; i++) if (HitEnemy(i)) Miss(); for (int i=0; i<num_bullet; i++) if (HitBullet(i)) Miss(); // 남은 시간이 다 되었다면 보통 상태로 이동함. time--; if (time<=0) { state=NORMAL; energy=0; } break; } }
void CCharacter::DoAttack( ) { //if(Status->Sleep <= 0xff) //{ // ClearBattle( Battle ); // return; // can't take any action while we are asleep can we? //} //Log(MSG_INFO,"skill type %i selected. Chartype = %i",Battle->atktype, CharType); if(Battle->iscasting == 1) { CCharacter* Enemy = GetCharTarget( ); if(Enemy == NULL) { ClearBattle( Battle ); return; } //Log(MSG_DEBUG,"Iscasting detected as true. Reset to false."); if(CanAttack()) { //if(IsPlayer()) //{ // Log(MSG_DEBUG,"Should reach here once on normal attack. iscasting state = %i",Battle->iscasting); //} ClearBattle( Battle ); StartAction(Enemy, NORMAL_ATTACK, 0); } else { return; } return; } if(!CanAttack()) { return; } if(IsSummon()) { CCharacter* Enemy = GetCharTarget( ); if(Enemy == NULL || (Battle->atktype != SKILL_AOE && Battle->atktype != BUFF_AOE)) { //Log(MSG_DEBUG,"No Enemy found"); ClearBattle( Battle ); return; } if(this == Enemy) //summoned monster is attacking itself. It has been observed to happen { //Log(MSG_INFO,"Clearing Battle for this summon"); ClearBattle( Battle ); return; } if(Enemy->IsSummon()) { CMonster* thisMonster = reinterpret_cast<CMonster*>(this); if(thisMonster == NULL) { ClearBattle( Battle ); return; } CMonster* otherMonster = reinterpret_cast<CMonster*>(Enemy); if(otherMonster == NULL) { ClearBattle( Battle ); return; } if(thisMonster->owner == otherMonster->owner) { //Log(MSG_INFO,"Clearing Battle for this summon"); ClearBattle( Battle ); return; } } } CMap* map = GServer->MapList.Index[Position->Map]; //Log(MSG_INFO,"DoAttack Battle Attack type = %i",Battle->atktype); switch(Battle->atktype) { case NORMAL_ATTACK://normal attack { //if(!Status->CanAttack) // return; //can't attack right now. CCharacter* Enemy = GetCharTarget( ); if(Enemy == NULL) { ClearBattle( Battle ); return; } if(Enemy == this) { //Log(MSG_INFO,"WTF?? I AM trying to attack myself"); ClearBattle( Battle ); } if(IsTargetReached( Enemy )) { //if(IsMonster()) // Log(MSG_INFO,"Monster is trying to hit the player"); NormalAttack( Enemy ); if (Enemy->IsMonster()) // do monster AI script when monster is attacked. { CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map); if(monster == NULL)return; //monster->DoAi(monster->thisnpc->AI, 3); monster->DoAi(monster->monAI, 3); } } } break; case SKILL_ATTACK://skill attack { CCharacter* Enemy = GetCharTarget( ); if(Enemy == NULL) { ClearBattle( Battle ); return; } CSkills* skill = GServer->GetSkillByID( Battle->skillid ); if(skill == NULL) { //ClearBattle( Battle ); return; } if(IsTargetReached( Enemy, skill )) { SkillAttack( Enemy, skill ); if (Enemy->IsMonster()) { CMonster* monster = GServer->GetMonsterByID(Enemy->clientid, Enemy->Position->Map); if(monster == NULL)return; monster->DoAi(monster->monAI, 3); } } } break; case SKILL_BUFF://buffs { CCharacter* Enemy = GetCharTarget( ); if(Enemy == NULL) { //Log(MSG_DEBUG,"this target is NULL"); ClearBattle( Battle ); return; } CSkills* skill = GServer->GetSkillByID( Battle->skillid ); if(skill == NULL) { //Log(MSG_DEBUG,"this skill is NULL"); return; } if(IsTargetReached( Enemy, skill )) { //Log(MSG_DEBUG,"Skill successfully cast"); BuffSkill( Enemy, skill ); } } break; case SKILL_AOE: //case SKILL_SELF: //this is impossible. it can never be set case AOE_TARGET: { //Log(MSG_DEBUG,"Called skill type %i",Battle->atktype); CCharacter* Enemy = NULL; CSkills* skill = GServer->GetSkillByID( Battle->skillid ); if(skill == NULL) { ClearBattle( Battle ); return; } if(Battle->atktype == AOE_TARGET) { float distance = GServer->distance( Position->current, Position->destiny ); if(distance <= skill->range) { Position->destiny = Position->current; AoeSkill( skill, Enemy ); } } else { Position->skilltargetpos = Position->current; AoeSkill( skill, NULL ); } } break; case BUFF_SELF: { // return; // can't cast skills right now CSkills* skill = GServer->GetSkillByID( Battle->skillid ); if(skill == NULL) { //ClearBattle( Battle ); return; } BuffSkill( this, skill ); } break; case BUFF_AOE: { //Log(MSG_INFO,"BUFF AOE selected"); CSkills* skill = GServer->GetSkillByID( Battle->skillid ); if(skill == NULL) { //ClearBattle( Battle ); return; } AoeBuff( skill ); } break; default: return; break; } }