1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-11 23:54:09 +02:00

#14 add mutant shooting

This commit is contained in:
XProger
2018-06-15 04:03:19 +03:00
parent 82b15b0366
commit f8e7ae14f6
3 changed files with 62 additions and 12 deletions

View File

@@ -112,7 +112,7 @@ struct Character : Controller {
} }
void rotateY(float delta) { void rotateY(float delta) {
angle.y += delta; angle.y = clampAngle(angle.y + delta);
velocity = velocity.rotateY(-delta); velocity = velocity.rotateY(-delta);
} }

View File

@@ -8,6 +8,8 @@
#define ESCAPE_BOX (1024 * 5) #define ESCAPE_BOX (1024 * 5)
#define ATTACK_BOX STALK_BOX #define ATTACK_BOX STALK_BOX
#define MAX_SHOT_DIST (64 * 1024)
struct Enemy : Character { struct Enemy : Character {
struct Path { struct Path {
@@ -68,6 +70,7 @@ struct Enemy : Character {
Path *path; Path *path;
float targetDist; float targetDist;
float targetAngle;
bool targetDead; bool targetDead;
bool targetInView; // target in enemy view zone bool targetInView; // target in enemy view zone
bool targetFromView; // enemy in target view zone bool targetFromView; // enemy in target view zone
@@ -319,6 +322,7 @@ struct Enemy : Character {
vec3 targetVec = target->pos - pos - getDir() * length; vec3 targetVec = target->pos - pos - getDir() * length;
targetDist = targetVec.length(); targetDist = targetVec.length();
targetAngle = atan2f(targetVec.x, targetVec.z) - angle.y;
targetDead = target->health <= 0; targetDead = target->health <= 0;
targetInView = targetVec.dot(getDir()) > 0; targetInView = targetVec.dot(getDir()) > 0;
targetFromView = targetVec.dot(target->getDir()) < 0; targetFromView = targetVec.dot(target->getDir()) < 0;
@@ -1793,6 +1797,7 @@ struct Raptor : Enemy {
#define MUTANT_DIST_ATTACK_1 600 #define MUTANT_DIST_ATTACK_1 600
#define MUTANT_DIST_ATTACK_2 (2048 + 512) #define MUTANT_DIST_ATTACK_2 (2048 + 512)
#define MUTANT_DIST_ATTACK_3 300 #define MUTANT_DIST_ATTACK_3 300
#define MUTANT_DIST_SHOT 3840
#define MUTANT_DIST_STALK (4096 + 512) #define MUTANT_DIST_STALK (4096 + 512)
struct Mutant : Enemy { struct Mutant : Enemy {
@@ -1818,6 +1823,12 @@ struct Mutant : Enemy {
STATE_FLY, STATE_FLY,
}; };
enum {
FLAG_FLY = 1,
FLAG_BULLET_1 = 2,
FLAG_BULLET_2 = 4,
};
Mutant(IGame *game, int entity) : Enemy(game, entity, 50, 341, 150.0f, 1.0f) { Mutant(IGame *game, int entity) : Enemy(game, entity, 50, 341, 150.0f, 1.0f) {
if (getEntity().type != TR::Entity::ENEMY_MUTANT_1) { if (getEntity().type != TR::Entity::ENEMY_MUTANT_1) {
initMeshOverrides(); initMeshOverrides();
@@ -1825,9 +1836,9 @@ struct Mutant : Enemy {
aggression = 0.25f; aggression = 0.25f;
} }
flags.unused = 0;
jointChest = 1; jointChest = 1;
jointHead = 2; jointHead = 2;
nextState = 0;
} }
virtual void update() { virtual void update() {
@@ -1853,20 +1864,38 @@ struct Mutant : Enemy {
if (nextState == state) if (nextState == state)
nextState = STATE_NONE; nextState = STATE_NONE;
if (getEntity().type != TR::Entity::ENEMY_MUTANT_3) {
if (flags.unused & (FLAG_BULLET_1 | FLAG_BULLET_2)) {
if (targetAngle > PI * 0.25f)
flags.unused &= ~(FLAG_BULLET_1 | FLAG_BULLET_2);
} else {
if (targetAngle < PI * 0.25f && state != STATE_FIRE && (targetDist > MUTANT_DIST_SHOT || zone != target->zone) && targetIsVisible(MAX_SHOT_DIST))
flags.unused |= (rand() % 2) ? FLAG_BULLET_1 : FLAG_BULLET_2;
}
}
int mask = collide(target); int mask = collide(target);
switch (state) { switch (state) {
case STATE_IDLE : case STATE_IDLE :
return STATE_STOP; return STATE_STOP;
case STATE_STOP : case STATE_STOP :
if (flags.unused & FLAG_FLY)
return STATE_FLY;
if ((targetCanAttack && targetDist < MUTANT_DIST_ATTACK_3) || (mask & HIT_MASK)) if ((targetCanAttack && targetDist < MUTANT_DIST_ATTACK_3) || (mask & HIT_MASK))
return STATE_ATTACK_3; return STATE_ATTACK_3;
if ((targetCanAttack && targetDist < MUTANT_DIST_ATTACK_1)) if ((targetCanAttack && targetDist < MUTANT_DIST_ATTACK_1))
return STATE_ATTACK_1; return STATE_ATTACK_1;
if (flags.unused & FLAG_BULLET_1)
return STATE_AIM_1;
if (flags.unused & FLAG_BULLET_2)
return STATE_AIM_2;
if (mood == MOOD_SLEEP || (mood == MOOD_STALK && targetDist < MUTANT_DIST_STALK)) if (mood == MOOD_SLEEP || (mood == MOOD_STALK && targetDist < MUTANT_DIST_STALK))
return STATE_LOOKING; return STATE_LOOKING;
return STATE_RUN; return STATE_RUN;
case STATE_LOOKING : case STATE_LOOKING :
if (flags.unused)
return STATE_STOP;
switch (mood) { switch (mood) {
case MOOD_SLEEP : case MOOD_SLEEP :
if (rand() < 256) if (rand() < 256)
@@ -1884,6 +1913,8 @@ struct Mutant : Enemy {
return STATE_STOP; return STATE_STOP;
} }
case STATE_WALK : case STATE_WALK :
if (flags.unused)
return STATE_STOP;
if (mood == MOOD_ATTACK || mood == MOOD_ESCAPE) if (mood == MOOD_ATTACK || mood == MOOD_ESCAPE)
return STATE_STOP; return STATE_STOP;
if (mood == MOOD_SLEEP || (mood == MOOD_STALK && target->zone != zone)) { if (mood == MOOD_SLEEP || (mood == MOOD_STALK && target->zone != zone)) {
@@ -1899,9 +1930,22 @@ struct Mutant : Enemy {
return STATE_STOP; return STATE_STOP;
if (targetInView && targetDist < MUTANT_DIST_ATTACK_2) if (targetInView && targetDist < MUTANT_DIST_ATTACK_2)
return STATE_ATTACK_2; return STATE_ATTACK_2;
if (flags.unused & (FLAG_BULLET_1 | FLAG_BULLET_2))
return STATE_STOP;
if (mood == MOOD_SLEEP || (mood == MOOD_STALK && targetDist < MUTANT_DIST_STALK)) if (mood == MOOD_SLEEP || (mood == MOOD_STALK && targetDist < MUTANT_DIST_STALK))
return STATE_STOP; return STATE_STOP;
break; break;
case STATE_AIM_1 :
return (flags.unused & FLAG_BULLET_1) ? STATE_FIRE : STATE_STOP;
case STATE_AIM_2 :
return (flags.unused & FLAG_BULLET_2) ? STATE_FIRE : STATE_STOP;
case STATE_FIRE :
if (flags.unused & FLAG_BULLET_1)
shot(TR::Entity::MUTANT_BULLET, 9, vec3(-35.0f, 269.0f, 0.0f));
if (flags.unused & FLAG_BULLET_2)
shot(TR::Entity::CENTAUR_BULLET, 14, vec3(51.0f, 213.0f, 0.0f));
flags.unused &= ~(FLAG_BULLET_1 | FLAG_BULLET_2);
break;
case STATE_ATTACK_1 : case STATE_ATTACK_1 :
case STATE_ATTACK_2 : case STATE_ATTACK_2 :
case STATE_ATTACK_3 : case STATE_ATTACK_3 :
@@ -1985,7 +2029,6 @@ struct GiantMutant : Enemy {
#define CENTAUR_TURN_FAST (DEG2RAD * 120) #define CENTAUR_TURN_FAST (DEG2RAD * 120)
#define CENTAUR_DIST_RUN (1024 + 512) #define CENTAUR_DIST_RUN (1024 + 512)
#define CENTAUR_DIST_SHOT (1024 * 1024)
struct Centaur : Enemy { struct Centaur : Enemy {
@@ -2025,7 +2068,7 @@ struct Centaur : Enemy {
return nextState; return nextState;
if (targetCanAttack && targetDist < CENTAUR_DIST_RUN) if (targetCanAttack && targetDist < CENTAUR_DIST_RUN)
return STATE_RUN; return STATE_RUN;
if (targetIsVisible(CENTAUR_DIST_SHOT)) if (targetIsVisible(MAX_SHOT_DIST))
return STATE_AIM; return STATE_AIM;
return STATE_RUN; return STATE_RUN;
case STATE_RUN : case STATE_RUN :
@@ -2033,7 +2076,7 @@ struct Centaur : Enemy {
nextState = STATE_IDLE; nextState = STATE_IDLE;
return STATE_STOP; return STATE_STOP;
} }
if (targetIsVisible(CENTAUR_DIST_SHOT)) { if (targetIsVisible(MAX_SHOT_DIST)) {
nextState = STATE_AIM; nextState = STATE_AIM;
return STATE_STOP; return STATE_STOP;
} }
@@ -2045,7 +2088,7 @@ struct Centaur : Enemy {
case STATE_AIM : case STATE_AIM :
if (nextState != STATE_NONE) if (nextState != STATE_NONE)
return nextState; return nextState;
if (targetIsVisible(CENTAUR_DIST_SHOT)) if (targetIsVisible(MAX_SHOT_DIST))
return STATE_FIRE; return STATE_FIRE;
return STATE_STOP; return STATE_STOP;
case STATE_FIRE : case STATE_FIRE :

View File

@@ -1549,6 +1549,7 @@ struct StoneItem : Controller {
#define CENTAUR_BULLET_DIST SQR(1024.0f) #define CENTAUR_BULLET_DIST SQR(1024.0f)
#define CENTAUR_BULLET_DAMAGE 100.0f #define CENTAUR_BULLET_DAMAGE 100.0f
#define MUTANT_BULLET_DAMAGE 30.0f
struct Bullet : Controller { struct Bullet : Controller {
vec3 velocity; vec3 velocity;
@@ -1596,7 +1597,6 @@ struct Bullet : Controller {
case TR::Entity::CENTAUR_BULLET : case TR::Entity::CENTAUR_BULLET :
if (directHit) { if (directHit) {
lara->hit(CENTAUR_BULLET_DAMAGE); lara->hit(CENTAUR_BULLET_DAMAGE);
game->playSound(lara->stand == Character::STAND_UNDERWATER ? TR::SND_HIT_UNDERWATER : TR::SND_HIT, lara->pos, Sound::PAN);
} else { } else {
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
Controller *lara = game->getLara(i); Controller *lara = game->getLara(i);
@@ -1611,10 +1611,17 @@ struct Bullet : Controller {
game->addEntity(TR::Entity::EXPLOSION, getRoomIndex(), pos); game->addEntity(TR::Entity::EXPLOSION, getRoomIndex(), pos);
break; break;
case TR::Entity::MUTANT_BULLET : case TR::Entity::MUTANT_BULLET :
game->getLara()->addRicochet(pos, true); if (directHit)
lara->hit(MUTANT_BULLET_DAMAGE);
else
game->getLara()->addRicochet(pos - getDir() * 64.0f, true);
break; break;
default : ; default : ;
} }
if (directHit)
game->playSound(lara->stand == Character::STAND_UNDERWATER ? TR::SND_HIT_UNDERWATER : TR::SND_HIT, lara->pos, Sound::PAN);
game->removeEntity(this); game->removeEntity(this);
} }
}; };