diff --git a/src/camera.h b/src/camera.h index 4faaa56..5ffb397 100644 --- a/src/camera.h +++ b/src/camera.h @@ -204,10 +204,8 @@ struct Camera : ICamera { uint16 ownerBoxIndex = level->getSector(target.room, target.pos)->boxIndex; uint16 cameraBoxIndex = level->getSector(to.room, to.pos)->boxIndex; - if (ownerBoxIndex == TR::NO_BOX) { - ASSERT(false); // TODO: collide death AABB with walls + if (ownerBoxIndex == TR::NO_BOX) return; - } TR::Box cBox = level->boxes[ownerBoxIndex]; if (cameraBoxIndex != TR::NO_BOX && !level->boxes[ownerBoxIndex].contains(int(to.pos.x), int(to.pos.z))) diff --git a/src/character.h b/src/character.h index c314926..7e86944 100644 --- a/src/character.h +++ b/src/character.h @@ -99,7 +99,7 @@ struct Character : Controller { int dx, dz; TR::Room::Sector &s = level->getSector(getRoomIndex(), int(pos.x), int(pos.z), dx, dz); - if (s.boxIndex == 0xFFFF) + if (s.boxIndex == TR::NO_BOX) return false; box = s.boxIndex; zone = getZones()[box]; diff --git a/src/controller.h b/src/controller.h index b10e6a5..746e14a 100644 --- a/src/controller.h +++ b/src/controller.h @@ -1210,12 +1210,12 @@ struct Controller { continue; explodeMask |= (1 << i); float angle = randf() * PI * 2.0f; - float speed = randf() * 256.0f; + vec2 speed = vec2(randf(), -randf()) * (getEntity().type == TR::Entity::ENEMY_GIANT_MUTANT ? 256.0f : 128.0f); ExplodePart &part = explodeParts[i]; part.basis = joints[i]; part.basis.w = 1.0f; - part.velocity = vec3(cosf(angle), (randf() - 0.5f) * 0.25f, sinf(angle)) * speed; + part.velocity = vec3(cosf(angle) * speed.x, speed.y, sinf(angle) * speed.x); part.roomIndex = roomIndex; } } diff --git a/src/enemy.h b/src/enemy.h index e172abb..98cd949 100644 --- a/src/enemy.h +++ b/src/enemy.h @@ -322,7 +322,7 @@ struct Enemy : Character { vec3 targetVec = target->pos - pos - getDir() * length; targetDist = targetVec.length(); - targetAngle = atan2f(targetVec.x, targetVec.z) - angle.y; + targetAngle = clampAngle(atan2f(targetVec.x, targetVec.z) - angle.y); targetDead = target->health <= 0; targetInView = targetVec.dot(getDir()) > 0; targetFromView = targetVec.dot(target->getDir()) < 0; @@ -1975,13 +1975,13 @@ struct Mutant : Enemy { } }; - -#define GIANT_MUTANT_TURN_SLOW (DEG2RAD * 90) -#define GIANT_MUTANT_MAX_ANGLE (DEG2RAD * 45) -#define GIANT_MUTANT_DAMAGE 500 -#define GIANT_MUTANT_DAMAGE_WALK 5 -#define GIANT_MUTANT_DIST_ATTACK 2600 -#define GIANT_MUTANT_DIST_FATAL 2250 +#define GIANT_MUTANT_TURN_SLOW (DEG2RAD * 90) +#define GIANT_MUTANT_MAX_ANGLE (DEG2RAD * 45) +#define GIANT_MUTANT_DAMAGE 500 +#define GIANT_MUTANT_DAMAGE_WALK 5 +#define GIANT_MUTANT_DAMAGE_FATAL 1000 +#define GIANT_MUTANT_DIST_ATTACK 2600 +#define GIANT_MUTANT_DIST_FATAL 2250 struct GiantMutant : Enemy { @@ -2027,13 +2027,13 @@ struct GiantMutant : Enemy { flags.state = TR::Entity::asActive; game->playSound(TR::SND_MUTANT_DEATH, pos, 0); explode(0xffffffff); + game->checkTrigger(this, true); } setOverrides(true, jointChest, jointHead); lookAt(target); if (exploded && !explodeMask) { - game->checkTrigger(this, true); deactivate(true); flags.invisible = true; } @@ -2052,6 +2052,9 @@ struct GiantMutant : Enemy { if (!think(true)) return state; + if (!target || target->health <= 0.0f) + return STATE_STOP; + int mask = collide(target); if (mask) target->hit(GIANT_MUTANT_DAMAGE_WALK, this); @@ -2063,8 +2066,8 @@ struct GiantMutant : Enemy { break; case STATE_STOP : flags.unused = false; - //if (targetAngle > GIANT_MUTANT_MAX_ANGLE) return STATE_TURN_RIGHT; - //if (targetAngle < -GIANT_MUTANT_MAX_ANGLE) return STATE_TURN_LEFT; + if (targetAngle > GIANT_MUTANT_MAX_ANGLE) return STATE_TURN_RIGHT; + if (targetAngle < -GIANT_MUTANT_MAX_ANGLE) return STATE_TURN_LEFT; if (targetDist < GIANT_MUTANT_DIST_ATTACK) { if (target->health <= GIANT_MUTANT_DAMAGE) { if (targetDist < GIANT_MUTANT_DIST_FATAL) @@ -2079,7 +2082,6 @@ struct GiantMutant : Enemy { targetAngle < -GIANT_MUTANT_MAX_ANGLE) return STATE_STOP; break; - /* case STATE_TURN_RIGHT : if (targetAngle < GIANT_MUTANT_MAX_ANGLE) return STATE_STOP; @@ -2088,7 +2090,6 @@ struct GiantMutant : Enemy { if (targetAngle > -GIANT_MUTANT_MAX_ANGLE) return STATE_STOP; break; - */ case STATE_ATTACK_1 : case STATE_ATTACK_2 : if (!flags.unused && ( @@ -2098,14 +2099,9 @@ struct GiantMutant : Enemy { flags.unused = true; } break; - /* - case STATE_IDLE : - if (nextState == STATE_NONE && (collide(target) & HIT_MASK)) { - bite(5, vec3(50.0f, 30.0f, 0.0f), 200); - nextState = STATE_STOP; - } - break; - */ + case STATE_ATTACK_3 : + target->hit(GIANT_MUTANT_DAMAGE_FATAL, this, TR::HIT_GIANT_MUTANT); + return STATE_FATAL; default : ; } @@ -2119,11 +2115,9 @@ struct GiantMutant : Enemy { } virtual void updatePosition() { - float angleY = 0.0f; - getTargetInfo(0, NULL, NULL, &angleY, NULL); - - if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_WALK || state == STATE_STOP) - turn(angleY, GIANT_MUTANT_TURN_SLOW); + if (target && target->health > 0.0f) + if (state == STATE_TURN_LEFT || state == STATE_TURN_RIGHT || state == STATE_WALK || state == STATE_STOP) + turn(targetAngle, GIANT_MUTANT_TURN_SLOW); Enemy::updatePosition(); //setOverrides(true, jointChest, jointHead); diff --git a/src/format.h b/src/format.h index fc06bfd..b7c55ca 100644 --- a/src/format.h +++ b/src/format.h @@ -996,6 +996,7 @@ namespace TR { HIT_REX, HIT_LIGHTNING, HIT_MIDAS, + HIT_GIANT_MUTANT, }; struct Action { diff --git a/src/lara.h b/src/lara.h index 8bb1004..270ec56 100644 --- a/src/lara.h +++ b/src/lara.h @@ -1537,6 +1537,15 @@ struct Lara : Character { camera->doCutscene(pos, angle.y); break; } + case TR::HIT_GIANT_MUTANT : { +// camera->setAngle(-25, 170); + pos = enemy->pos; + angle = enemy->angle; + + animation.setAnim(level->models[TR::MODEL_LARA_SPEC].animation); + break; + } + default : ; }