| 269 | } |
| 270 | |
| 271 | void ShivaControl(short itemNumber) |
| 272 | { |
| 273 | if (!CreatureActive(itemNumber)) |
| 274 | return; |
| 275 | |
| 276 | auto* item = &g_Level.Items[itemNumber]; |
| 277 | const auto& object = Objects[item->ObjectNumber]; |
| 278 | auto& creature = *GetCreatureInfo(item); |
| 279 | |
| 280 | short headingAngle = 0; |
| 281 | short tiltAngle = 0; |
| 282 | auto extraHeadRot = EulerAngles::Identity; |
| 283 | auto extraTorsoRot = EulerAngles::Identity; |
| 284 | |
| 285 | if (item->HitPoints <= 0) |
| 286 | { |
| 287 | if (item->Animation.ActiveState != SHIVA_STATE_DEATH) |
| 288 | { |
| 289 | SetAnimation(item, SHIVA_ANIM_DEATH); |
| 290 | item->ItemFlags[0] = object.nmeshes - 1; |
| 291 | item->ItemFlags[2] = 1; // Do mesh swap to stone. |
| 292 | item->ItemFlags[3] = 1; |
| 293 | } |
| 294 | |
| 295 | if (TestLastFrame(*item)) |
| 296 | { |
| 297 | // Block last frame until mesh is swapped. |
| 298 | item->Animation.FrameNumber = GetAnimData(*item).EndFrameNumber - 1; |
| 299 | |
| 300 | if (DoShivaMeshSwap(*item, true)) |
| 301 | CreatureDie(itemNumber, false); |
| 302 | } |
| 303 | } |
| 304 | else |
| 305 | { |
| 306 | AI_INFO ai; |
| 307 | CreatureAIInfo(item, &ai); |
| 308 | |
| 309 | GetCreatureMood(item, &ai, true); |
| 310 | CreatureMood(item, &ai, true); |
| 311 | |
| 312 | // Shiva isn't fearful. |
| 313 | if (creature.Mood == MoodType::Escape) |
| 314 | { |
| 315 | creature.Target.x = creature.Enemy->Pose.Position.x; |
| 316 | creature.Target.z = creature.Enemy->Pose.Position.z; |
| 317 | } |
| 318 | |
| 319 | bool isPlayerAlive = (creature.Enemy->HitPoints > 0); |
| 320 | headingAngle = CreatureTurn(item, creature.MaxTurn); |
| 321 | |
| 322 | switch (item->Animation.ActiveState) |
| 323 | { |
| 324 | case SHIVA_STATE_INACTIVE: |
| 325 | creature.MaxTurn = 0; |
| 326 | |
| 327 | if (DoShivaMeshSwap(*item, false)) |
| 328 | item->Animation.TargetState = SHIVA_STATE_IDLE; |
nothing calls this directly
no test coverage detected