int ActorStateMachine::AttackEnemy(float enemyPos[3], SHOT_CODE *shot_code){
	if (shot_code != NULL){
		*shot_code = FALSE;
	}
	// the return value is the attack power
	FnActor actor;
	actor.Object(this->character);
	float attackerPos[3], attackerDir[3];
	actor.GetWorldPosition(attackerPos);
	actor.GetWorldDirection(attackerDir,NULL);
	float frame = actor.QueryCurrentFrame(0);

	float dist = 0.0;
	for (int i = 0;i< 3;i++){
		dist += (attackerPos[i] - enemyPos[i]) * (attackerPos[i] - enemyPos[i]);
	}
	//sprintf(debug, "%s dist = %lf\n",debug,dist);
	if ( dist >= ROBOT_ATTACKRANGE ){
		return 0; // no attack power
	}
	float cosine,dotProduct;
	//float v[3];
	dotProduct = 0.0;
	for (int i = 0;i< 3;i++){
		dotProduct += (enemyPos[i] - attackerPos[i]) * attackerDir[i];
	}
	float length = 0.0;
	for (int i = 0;i< 3;i++){
		length += (enemyPos[i] - attackerPos[i])* (enemyPos[i] - attackerPos[i]);
	}
	cosine = dotProduct / sqrt(length);
	//sprintf(debug, "%s cosine = %lf\n",debug,cosine);

	if (this->attackKeyQueue[currentAttackIndex] == HEAVY_ATT || currentAttackIndex == MAXATTACK -1){
		*shot_code = BIG_SHOT;
	}else {
		*shot_code = SMALL_SHOT;
	}

	if (this->currentAttackIndex == 0){
		if (cosine > 0.8){ // normal or heavy attack, only attack the front side enemy
			//sprintf(debug, "%s attack power = %d\n",debug,1);
			return 1;
		}
	}else if (this->currentAttackIndex <= 3){
		if (cosine >= 0.0){
			//sprintf(debug, "%s attack power = %d\n",debug,2);
			return 3;
		}
	}
	return 0;
}
void ActorStateMachine::TakeDamage(int damage, SHOT_CODE shot_code, float *attackerPos ){
	FnActor actor;
	actor.Object(character);
	float pos[3];
	float dir[3];
	actor.GetWorldPosition(pos);
	actor.GetWorldDirection(dir, NULL);
	if ( shot_code != STUCK_SHOT && attackerPos !=NULL){
		float newDir[3];
		newDir[0] = attackerPos[0] - pos[0];
		newDir[1] = attackerPos[1] - pos[1];
		newDir[2] = 0.0f;
		actor.SetWorldDirection(newDir,NULL);
		if (shot_code == BIG_SHOT){
			actor.MoveForward(-OUTSHOT_DIS,TRUE, FALSE, 0.0, TRUE);
			//sprintf(debug, "%s OUTSHOT_DIS\n", debug);
		}else if (shot_code == SMALL_SHOT){
			actor.MoveForward(-SMALL_OUTSHOT_DIS,TRUE, FALSE, 0.0, TRUE);
			//sprintf(debug, "%s SMALL_OUTSHOT_DIS\n", debug);
		}
		actor.SetWorldDirection(dir,NULL);
	}

	if (this->state == STATEGUARD){
		FnAudio audio;
		audio.Object(audioG);
		audio.Play(ONCE);
		return; // no damage
	}else{
		FnAudio audio;
		audio.Object(audioD);
		//if (audio.IsPlaying() == FALSE){
			audio.Play(ONCE);
		//}
		

	}
	this->life -= damage;
	//sprintf(debug, "%s life=%d\n", debug, this->life);
	if (this->life <= 0) {
		this->ChangeState(STATEDIE, TRUE);
	}else {
		this->ChangeState(STATEDAMAGE, TRUE);
	}
	this->UpdateLifeBillboard();
}
Example #3
0
void AIControl::moveTowardLyubu() {
	for (int i = 0;i< this->npcStateMachineList.size(); i++){
		if (npcStateMachineList[i]->CanBeControl() == FALSE){
			continue;
		}
		int npcId = npcStateMachineList[i]->character;
		FnActor lyubu;
		FnActor npc;
		lyubu.Object(this->lyubuId);
		npc.Object(npcId);

		float lyubuPos[3];
		float npcPos[3];

		lyubu.GetWorldPosition(lyubuPos);
		npc.GetWorldPosition(npcPos);

		float distance;
		distance = sqrt((npcPos[0] - lyubuPos[0]) * (npcPos[0] - lyubuPos[0]) 
			+ (npcPos[1] - lyubuPos[1])	* (npcPos[1] - lyubuPos[1]));
			//+ (npcPos[2] - lyubuPos[2]) * (npcPos[2] - lyubuPos[2]));
		
		//sprintf(debug, "%s x = %f y = %f z = %f\n",debug, lyubuPos[0], lyubuPos[1], lyubuPos[2]);

		if (distance > ATTACK_DISTANCE && ((npcStateMachineList[i] == this->bossStateMachine && distance < BOSS_KEEP_TRACK_DISTANCE) || distance < KEEP_TRACK_DISTANCE)) {
			//turn toward lyubu
			float newFDir[3], normalize, offset;
			if (npcStateMachineList[i] != this->bossStateMachine) {
				srand ( time(NULL) + i);
				offset = rand() % NPC_MOVE_OFFSET + 1;
				lyubuPos[0] += offset;
				lyubuPos[1] += offset;
				lyubuPos[2] += offset;
			}

			newFDir[0] = lyubuPos[0] - npcPos[0];
			newFDir[1] = lyubuPos[1] - npcPos[1];
			newFDir[2] = lyubuPos[2] - npcPos[2];
			normalize = sqrt(newFDir[0] * newFDir[0] + newFDir[1] * newFDir[1] + newFDir[2] * newFDir[2]);
			newFDir[0] /= normalize;
			newFDir[1] /= normalize;
			newFDir[2] /= normalize;

			float npcFDir[3], npcUDir[3];
			npc.GetWorldDirection(npcFDir, npcUDir);
			npc.SetWorldDirection(newFDir, npcUDir);

			//move forward
			int block = npc.MoveForward(MOVE_DISTANCE,TRUE, FALSE, 0.0, TRUE);
			if (block) {
				//sprintf(debug, "%s npc is blocked\n",debug);
				while (npc.MoveForward(MOVE_DISTANCE,TRUE, FALSE, 0.0, TRUE)) {
					sprintf(debug, "%s npc turn right\n",debug);
					npc.TurnRight(300);
					npc.MoveForward(MOVE_DISTANCE,TRUE, FALSE, 0.0, TRUE);
				}
			}
			npcStateMachineList[i]->ChangeState(STATERUN, FALSE);
		}
		else if (distance <= ATTACK_DISTANCE) {
			//before attack, turn toward lyubu
			float newFDir[3], normalize, offset;

			newFDir[0] = lyubuPos[0] - npcPos[0];
			newFDir[1] = lyubuPos[1] - npcPos[1];
			newFDir[2] = lyubuPos[2] - npcPos[2];
			normalize = sqrt(newFDir[0] * newFDir[0] + newFDir[1] * newFDir[1] + newFDir[2] * newFDir[2]);
			newFDir[0] /= normalize;
			newFDir[1] /= normalize;
			newFDir[2] /= normalize;

			float npcFDir[3], npcUDir[3];
			npc.GetWorldDirection(npcFDir, npcUDir);
			npc.SetWorldDirection(newFDir, npcUDir);

			//sprintf(debug, "%s distance = %f\n",debug,distance);
			srand ( time(NULL) + i);
			float rate = rand() % 100;
			if (this->npcStateMachineList[i] == this->bossStateMachine){
				if (rate > GUARD_RATE ) {
					npcStateMachineList[i]->AppendAttackCode(NORMAL_ATT);
					npcStateMachineList[i]->AppendAttackCode(NORMAL_ATT);
					npcStateMachineList[i]->AppendAttackCode(HEAVY_ATT);
				}else{
					npcStateMachineList[i]->CharacterSetGuard();
				}
			}else {
				if (rate > GUARD_RATE * 2) {
					npcStateMachineList[i]->AppendAttackCode(NORMAL_ATT);
				}
				else{
					npcStateMachineList[i]->CharacterSetIdle();
				}
			}
		}
		else {
			npcStateMachineList[i]->CharacterSetIdle();
		}
	}
}