shithub: choc

Download patch

ref: 5eeef20d70fc978372058371d29821dc27b019a5
parent: 3e70ef4cf909ba4254258e176f92ab6c931993cb
author: Simon Howard <fraggle@soulsphere.org>
date: Thu Nov 27 10:28:58 EST 2014

hexen: Store minotaur start time as little endian.

The minotaur uses the first four bytes of the mobj_t args[] array to
store its spawn time; after a certain amount of time has passed the
minotaur self-destructs. But the level time was being copied from the
leveltime variable without any endian conversion taking place. For
compatibility with Vanilla Hexen savegames we need to store the start
time in little endian format.

This fixes the first issue noted in #477 (thanks Quasar).

--- a/src/hexen/a_action.c
+++ b/src/hexen/a_action.c
@@ -636,7 +636,12 @@
             return;
         }
 
-        memcpy((void *) mo->args, &leveltime, sizeof(leveltime));
+        // Store leveltime into mo->args. This must be stored in little-
+        // endian format for Vanilla savegame compatibility.
+        mo->args[0] = leveltime & 0xff;
+        mo->args[1] = (leveltime >> 8) & 0xff;
+        mo->args[2] = (leveltime >> 16) & 0xff;
+        mo->args[3] = (leveltime >> 24) & 0xff;
         master = actor->special1.m;
         if (master->flags & MF_CORPSE)
         {                       // Master dead
--- a/src/hexen/p_enemy.c
+++ b/src/hexen/p_enemy.c
@@ -1108,16 +1108,33 @@
 
 void A_MinotaurLook(mobj_t * actor);
 
-void A_MinotaurRoam(mobj_t * actor)
+// Check the age of the minotaur and stomp it after MAULATORTICS of time
+// have passed. Returns false if killed.
+static boolean CheckMinotaurAge(mobj_t *mo)
 {
-    unsigned int *starttime = (unsigned int *) actor->args;
+    unsigned int starttime;
 
+    // The start time is stored in the mobj_t structure, but it is stored
+    // in little endian format. For Vanilla savegame compatibility we must
+    // swap it to the native endianness.
+    memcpy(&starttime, mo->args, sizeof(unsigned int));
+
+    if (leveltime - LONG(starttime) >= MAULATORTICS)
+    {
+        P_DamageMobj(mo, NULL, NULL, 10000);
+        return false;
+    }
+
+    return true;
+}
+
+void A_MinotaurRoam(mobj_t * actor)
+{
     actor->flags &= ~MF_SHADOW; // In case pain caused him to 
     actor->flags &= ~MF_ALTSHADOW;      // skip his fade in.
 
-    if ((leveltime - *starttime) >= MAULATORTICS)
+    if (!CheckMinotaurAge(actor))
     {
-        P_DamageMobj(actor, NULL, NULL, 10000);
         return;
     }
 
@@ -1231,14 +1248,11 @@
 
 void A_MinotaurChase(mobj_t * actor)
 {
-    unsigned int *starttime = (unsigned int *) actor->args;
-
     actor->flags &= ~MF_SHADOW; // In case pain caused him to 
     actor->flags &= ~MF_ALTSHADOW;      // skip his fade in.
 
-    if ((leveltime - *starttime) >= MAULATORTICS)
+    if (!CheckMinotaurAge(actor))
     {
-        P_DamageMobj(actor, NULL, NULL, 10000);
         return;
     }