diff --git a/src/dehacked.c b/src/dehacked.c index 3a766df3..7b6fce01 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -716,7 +716,15 @@ static void readfollower(MYFILE *f) s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); - CONS_Printf("Adding follower...\n"); + // Ready the default variables for followers. We will overwrite them as we go! We won't set the name or states RIGHT HERE as this is handled down instead. + followers[numfollowers].scale = FRACUNIT; + followers[numfollowers].atangle = 230; + followers[numfollowers].dist = 16; + followers[numfollowers].zoffs = 32; + followers[numfollowers].horzlag = 2; + followers[numfollowers].vertlag = 4; + followers[numfollowers].bobspeed = TICRATE*2; + followers[numfollowers].bobamp = 4; do { @@ -751,11 +759,36 @@ static void readfollower(MYFILE *f) strcpy(followers[numfollowers].name, word2); nameset = true; } + else if (fastcmp(word, "SCALE")) + { + DEH_WriteUndoline(word, va("%d", followers[numfollowers].scale), UNDO_NONE); + followers[numfollowers].scale = get_number(word2); + } else if (fastcmp(word, "ATANGLE")) { DEH_WriteUndoline(word, va("%d", followers[numfollowers].atangle), UNDO_NONE); followers[numfollowers].atangle = (INT32)atoi(word2); } + else if (fastcmp(word, "HORZLAG")) + { + DEH_WriteUndoline(word, va("%d", followers[numfollowers].horzlag), UNDO_NONE); + followers[numfollowers].horzlag = (INT32)atoi(word2); + } + else if (fastcmp(word, "VERTLAG")) + { + DEH_WriteUndoline(word, va("%d", followers[numfollowers].vertlag), UNDO_NONE); + followers[numfollowers].vertlag = (INT32)atoi(word2); + } + else if (fastcmp(word, "BOBSPEED")) + { + DEH_WriteUndoline(word, va("%d", followers[numfollowers].bobspeed), UNDO_NONE); + followers[numfollowers].bobspeed = (INT32)atoi(word2); + } + else if (fastcmp(word, "BOBAMP")) + { + DEH_WriteUndoline(word, va("%d", followers[numfollowers].bobamp), UNDO_NONE); + followers[numfollowers].bobamp = (INT32)atoi(word2); + } else if (fastcmp(word, "ZOFFSET") || (fastcmp(word, "ZOFFS"))) { DEH_WriteUndoline(word, va("%d", followers[numfollowers].zoffs), UNDO_NONE); @@ -824,7 +857,7 @@ static void readfollower(MYFILE *f) { INT32 startlen = strlen(testname); char cpy[2]; - deh_warning("There was already a follower with the same name. (%s)", testname); + //deh_warning("There was already a follower with the same name. (%s)", testname); This warning probably isn't necessary anymore? sprintf(cpy, "%d", numfollowers); memcpy(&testname[startlen], cpy, 2); // in that case, we'll be very lazy and copy numfollowers to the end of our skin name. @@ -841,8 +874,28 @@ static void readfollower(MYFILE *f) if (followers[numfollowers].zoffs < 0) followers[numfollowers].zoffs = 0; + // HORZLAG and VERTLAG must ABSOLUTELY be higher than 0. If 0, the game crashes, if negative, weird shit happens! + if (followers[numfollowers].horzlag <= 0) + followers[numfollowers].horzlag = 1; + + if (followers[numfollowers].vertlag <= 0) + followers[numfollowers].vertlag = 1; + + // scale must be positive for obvious reasons, and so must both of the bob related variables + if (followers[numfollowers].scale <= 0) + followers[numfollowers].scale = 1; + + // Bob amplitude can totally be 0 + if (followers[numfollowers].bobamp < 0) + followers[numfollowers].bobamp = 1; + + // so can bob speed + if (followers[numfollowers].bobspeed < 0) + followers[numfollowers].bobspeed = 1; + + // also check if we forgot states. If we did, we will set any missing state to the follower's idlestate. + // Print a warning in case we don't have a fallback and set the state to S_INVISIBLE (rather than S_NULL) if unavailable. - // also check if we forgot states :V #define NOSTATE(field, field2) \ if (!followers[numfollowers].field) \ { \ diff --git a/src/m_menu.c b/src/m_menu.c index 82df9020..17a71d2f 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -8348,12 +8348,14 @@ static void M_DrawSetupMultiPlayerMenu(void) if (setupm_fakecolor) // inverse should never happen { + // Fake the follower's in game appearance by now also applying some of its variables! coolio, eh? + follower_t fl = followers[setupm_fakefollower]; // shortcut for our sanity // smooth floating, totally not stolen from rocket sneakers. const fixed_t pi = (22<>ANGLETOFINESHIFT) & FINEMASK); + fixed_t sine = fl.bobamp * FINESINE((((8*pi*(fl.bobspeed)) * followertimer)>>ANGLETOFINESHIFT) & FINEMASK); UINT8 *colormap = R_GetTranslationColormap(-1, setupm_fakecolor, 0); - V_DrawMappedPatch(mx+65, my+90+(sine/FRACUNIT), flags, patch, colormap); + V_DrawFixedPatch((mx+65)*FRACUNIT, (my+131-fl.zoffs)*FRACUNIT+sine, fl.scale, flags, patch, colormap); Z_Free(colormap); } } diff --git a/src/p_user.c b/src/p_user.c index 7ca368b7..1b8748b2 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -8979,18 +8979,15 @@ static void P_HandleFollower(player_t *player) // ^ handled by K_matchgenericextraflags oops - // finally, add a cool floating effect to the z height, unless we have no zoffs, in which case I guess this means we WANT to be on the ground...??? - if (fl.zoffs) - { - // not stolen from k_kart I swear!! - const fixed_t pi = (22<>ANGLETOFINESHIFT) & FINEMASK); - sz += sine; - } + // finally, add a cool floating effect to the z height. + // not stolen from k_kart I swear!! + const fixed_t pi = (22<>ANGLETOFINESHIFT) & FINEMASK); + sz += sine; if (!player->follower) // follower doesn't exist / isn't valid { - CONS_Printf("Spawning follower...\n"); + //CONS_Printf("Spawning follower...\n"); // so let's spawn one! player->follower = P_SpawnMobj(sx, sy, sz, MT_FOLLOWER); P_SetFollowerState(player->follower, fl.idlestate); @@ -9012,14 +9009,14 @@ static void P_HandleFollower(player_t *player) P_SetFollowerState(player->follower, player->follower->state->nextstate); // move the follower next to us (yes, this is really basic maths but it looks pretty damn clean in practice)! - player->follower->momx = (sx - player->follower->x)/2; - player->follower->momy = (sy - player->follower->y)/2; - player->follower->momz = (sz - player->follower->z)/6; // make z momentum a bit floatier, it'll look cute I promise! + player->follower->momx = (sx - player->follower->x)/fl.horzlag; + player->follower->momy = (sy - player->follower->y)/fl.horzlag; + player->follower->momz = (sz - player->follower->z)/fl.vertlag; // make z momentum a bit floatier, it'll look cute I promise! player->follower->angle = player->mo->angle; player->follower->color = player->mo->color; player->follower->colorized = player->mo->colorized; - P_SetScale(player->follower, player->mo->scale); + P_SetScale(player->follower, FixedMul(fl.scale, player->mo->scale)); K_MatchGenericExtraFlags(player->follower, player->mo); @@ -9028,7 +9025,7 @@ static void P_HandleFollower(player_t *player) // hurt or dead if (player->kartstuff[k_spinouttimer] || player->mo->health <= 0) { - player->follower->angle = leveltime*48*ANG1; + player->follower->angle = -leveltime*48*ANG1; // spin out if (player->follower->extravalue1 != 2) { player->follower->extravalue1 = 2; @@ -9037,20 +9034,23 @@ static void P_HandleFollower(player_t *player) if (player->mo->health <= 0) // if dead, follow the player's z momentum exactly so they both look like they die at the same speed. player->follower->momz = player->mo->momz; } - else if (player->speed > 10*player->mo->scale) + else if (player->speed > 10*player->mo->scale) // animation for moving fast enough { + // if we're moving fast enough, let's make the angle the direction we're moving towards. This is to avoid drifting looking awkward. + player->follower->angle = R_PointToAngle2(0, 0, player->follower->momx, player->follower->momy); + if (player->follower->extravalue1 != 1) { player->follower->extravalue1 = 1; P_SetFollowerState(player->follower, fl.followstate); } } - else // nvm you're slow + else // animations when nearly still. This includes winning and losing. { if (player->follower->extravalue1 != 0) { - if (player->exiting) + if (player->exiting) // win/ loss animations { if (K_IsPlayerLosing(player)) // L { @@ -9069,7 +9069,7 @@ static void P_HandleFollower(player_t *player) } } } - else + else // normal standstill { player->follower->extravalue1 = 0; P_SetFollowerState(player->follower, fl.idlestate); diff --git a/src/r_things.c b/src/r_things.c index b5a7f711..f8d84b03 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -2775,7 +2775,7 @@ void SetFollower(INT32 playernum, INT32 skinnum) if (skinnum >= -1 && skinnum <= numfollowers) // Make sure it exists! { player->followerskin = skinnum; - CONS_Printf("Updated player follower num\n"); + //CONS_Printf("Updated player follower num\n"); /* We don't spawn the follower here since it'll be easier to handle all of it in the Player thinker itself. However, we will despawn it right here if there's any to make it easy for the player thinker to replace it or delete it. diff --git a/src/r_things.h b/src/r_things.h index cfb862f0..ec70bef7 100644 --- a/src/r_things.h +++ b/src/r_things.h @@ -124,11 +124,20 @@ typedef struct follower_s { char skinname[SKINNAMESIZE+1]; // Skin Name. This is what to refer to when asking the commands anything. char name[SKINNAMESIZE+1]; // Name. This is used for the menus. We'll just follow the same rules as skins for this. - + + fixed_t scale; // Scale relative to the player's. + // some position shenanigans: INT32 atangle; // angle the object will be at around the player. The object itself will always face the same direction as the player. INT32 dist; // distance relative to the player. (In a circle) INT32 zoffs; // Z offset relative to the player's height. Cannot be negative. + + // movement options + + INT32 horzlag; // Lag for X/Y displacement. Default is 2. Must be > 0 because we divide by this number. + INT32 vertlag; // not Vert from Neptunia lagging, this is for Z displacement lag Default is 4. Must be > 0 because we divide by this number. + INT32 bobamp; // Bob amplitude. Default is 4. + INT32 bobspeed; // Arbitrary modifier for bobbing speed, default is TICRATE*2 (70). // from there on out, everything is STATES to allow customization // these are only set once when the action is performed and are then free to animate however they want. @@ -138,7 +147,6 @@ typedef struct follower_s INT32 hurtstate; // state when the player is being hurt INT32 winstate; // state when the player has won INT32 losestate; // state when the player has lost - } follower_t; // -----------