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:
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
53
src/enemy.h
53
src/enemy.h
@@ -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 :
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user