diff --git a/extras/conf/udb/includes/Game_Kart2.cfg b/extras/conf/udb/Includes/Game_Kart2.cfg similarity index 100% rename from extras/conf/udb/includes/Game_Kart2.cfg rename to extras/conf/udb/Includes/Game_Kart2.cfg diff --git a/extras/conf/udb/includes/Kart2_common.cfg b/extras/conf/udb/Includes/Kart2_common.cfg similarity index 100% rename from extras/conf/udb/includes/Kart2_common.cfg rename to extras/conf/udb/Includes/Kart2_common.cfg diff --git a/extras/conf/udb/includes/Kart2_linedefs.cfg b/extras/conf/udb/Includes/Kart2_linedefs.cfg similarity index 100% rename from extras/conf/udb/includes/Kart2_linedefs.cfg rename to extras/conf/udb/Includes/Kart2_linedefs.cfg diff --git a/extras/conf/udb/includes/Kart2_misc.cfg b/extras/conf/udb/Includes/Kart2_misc.cfg similarity index 100% rename from extras/conf/udb/includes/Kart2_misc.cfg rename to extras/conf/udb/Includes/Kart2_misc.cfg diff --git a/extras/conf/udb/includes/Kart2_sectors.cfg b/extras/conf/udb/Includes/Kart2_sectors.cfg similarity index 100% rename from extras/conf/udb/includes/Kart2_sectors.cfg rename to extras/conf/udb/Includes/Kart2_sectors.cfg diff --git a/extras/conf/udb/includes/Kart2_things.cfg b/extras/conf/udb/Includes/Kart2_things.cfg similarity index 100% rename from extras/conf/udb/includes/Kart2_things.cfg rename to extras/conf/udb/Includes/Kart2_things.cfg diff --git a/src/d_main.c b/src/d_main.c index 8b437a8a3..57dcdefea 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1272,43 +1272,6 @@ void D_SRB2Main(void) if (M_CheckParm("-server") || dedicated) netgame = server = true; - if (M_CheckParm("-warp") && M_IsNextParm()) - { - const char *word = M_GetNextParm(); - char ch; // use this with sscanf to catch non-digits with - if (fastncmp(word, "MAP", 3)) // MAPxx name - pstartmap = M_MapNumber(word[3], word[4]); - else if (sscanf(word, "%d%c", &pstartmap, &ch) != 1) // a plain number - I_Error("Cannot warp to map %s (invalid map name)\n", word); - // Don't check if lump exists just yet because the wads haven't been loaded! - // Just do a basic range check here. - if (pstartmap < 1 || pstartmap > NUMMAPS) - I_Error("Cannot warp to map %d (out of range)\n", pstartmap); - else - { - if (!M_CheckParm("-server")) - { - G_SetGameModified(true, true); - - // Start up a "minor" grand prix session - memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); - - grandprixinfo.gamespeed = KARTSPEED_NORMAL; - grandprixinfo.encore = false; - grandprixinfo.masterbots = false; - - grandprixinfo.gp = true; - grandprixinfo.roundnum = 0; - grandprixinfo.cup = NULL; - grandprixinfo.wonround = false; - - grandprixinfo.initalize = true; - } - - autostart = true; - } - } - // adapt tables to SRB2's needs, including extra slots for dehacked file support P_PatchInfoTables(); @@ -1558,13 +1521,32 @@ void D_SRB2Main(void) if (M_CheckParm("-warp") && M_IsNextParm()) { const char *word = M_GetNextParm(); + pstartmap = G_FindMapByNameOrCode(word, 0); + if (! pstartmap) I_Error("Cannot find a map remotely named '%s'\n", word); else { if (!M_CheckParm("-server")) - G_SetGameModified(multiplayer, true); + { + G_SetGameModified(true, true); + + // Start up a "minor" grand prix session + memset(&grandprixinfo, 0, sizeof(struct grandprixinfo)); + + grandprixinfo.gamespeed = KARTSPEED_NORMAL; + grandprixinfo.encore = false; + grandprixinfo.masterbots = false; + + grandprixinfo.gp = true; + grandprixinfo.roundnum = 0; + grandprixinfo.cup = NULL; + grandprixinfo.wonround = false; + + grandprixinfo.initalize = true; + } + autostart = true; } } diff --git a/src/d_netcmd.c b/src/d_netcmd.c index 331f48623..998068a07 100644 --- a/src/d_netcmd.c +++ b/src/d_netcmd.c @@ -428,6 +428,7 @@ consvar_t cv_kartdebugdistribution = CVAR_INIT ("kartdebugdistribution", "Off", consvar_t cv_kartdebughuddrop = CVAR_INIT ("kartdebughuddrop", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL); static CV_PossibleValue_t kartdebugwaypoint_cons_t[] = {{0, "Off"}, {1, "Forwards"}, {2, "Backwards"}, {0, NULL}}; consvar_t cv_kartdebugwaypoints = CVAR_INIT ("kartdebugwaypoints", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, kartdebugwaypoint_cons_t, NULL); +consvar_t cv_kartdebugbotpredict = CVAR_INIT ("kartdebugbotpredict", "Off", CV_NETVAR|CV_CHEAT|CV_NOSHOWHELP, CV_OnOff, NULL); consvar_t cv_kartdebugcheckpoint = CVAR_INIT ("kartdebugcheckpoint", "Off", CV_NOSHOWHELP, CV_OnOff, NULL); consvar_t cv_kartdebugnodes = CVAR_INIT ("kartdebugnodes", "Off", CV_NOSHOWHELP, CV_OnOff, NULL); diff --git a/src/d_netcmd.h b/src/d_netcmd.h index 6a8cf0840..41dc3fdf7 100644 --- a/src/d_netcmd.h +++ b/src/d_netcmd.h @@ -88,7 +88,7 @@ extern consvar_t cv_votetime; extern consvar_t cv_kartdebugitem, cv_kartdebugamount, cv_kartallowgiveitem, cv_kartdebugshrink, cv_kartdebugdistribution, cv_kartdebughuddrop; extern consvar_t cv_kartdebugcheckpoint, cv_kartdebugnodes, cv_kartdebugcolorize; -extern consvar_t cv_kartdebugwaypoints; +extern consvar_t cv_kartdebugwaypoints, cv_kartdebugbotpredict; extern consvar_t cv_itemfinder; diff --git a/src/g_demo.c b/src/g_demo.c index f19efaa2b..8ca756723 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -3658,7 +3658,6 @@ void G_StopDemo(void) democam.soundmobj = NULL; democam.localangle = 0; democam.localaiming = 0; - democam.turnheld = false; democam.keyboardlook = false; if (gamestate == GS_INTERMISSION) diff --git a/src/g_game.c b/src/g_game.c index 93e8c498c..04fcf3508 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -863,8 +863,6 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect INT32 localaiming[MAXSPLITSCREENPLAYERS]; angle_t localangle[MAXSPLITSCREENPLAYERS]; -static INT32 angleturn[2] = {KART_FULLTURN, KART_FULLTURN / 4}; // + slow turn - void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) { const UINT8 forplayer = ssplayer-1; @@ -875,11 +873,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) const boolean gamepadjoystickmove = cv_usejoystick[forplayer].value && Joystick[forplayer].bGamepadStyle; const boolean usejoystick = (analogjoystickmove || gamepadjoystickmove); - static INT32 turnheld[MAXSPLITSCREENPLAYERS]; // for accelerative turning static boolean keyboard_look[MAXSPLITSCREENPLAYERS]; // true if lookup/down using keyboard static boolean resetdown[MAXSPLITSCREENPLAYERS]; // don't cam reset every frame - INT32 tspeed, forward, axis; + INT32 forward, axis; joystickvector2_t joystickvector; @@ -887,11 +884,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) player_t *player = &players[g_localplayers[forplayer]]; camera_t *thiscam = &camera[forplayer]; - INT32 *th = &turnheld[forplayer]; boolean *kbl = &keyboard_look[forplayer]; boolean *rd = &resetdown[forplayer]; const boolean mouseaiming = player->spectator; + (void)realtics; + if (demo.playback) return; // Is there any reason this can't just be I_BaseTiccmd? @@ -953,39 +951,27 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) } forward = 0; - // use two stage accelerative turning - // on the keyboard and joystick - if (turnleft || turnright) - *th += realtics; - else - *th = 0; - - if (*th < SLOWTURNTICS) - tspeed = 1; // slow turn - else - tspeed = 0; - cmd->turning = 0; // let movement keys cancel each other out if (turnright && !(turnleft)) { - cmd->turning = (INT16)(cmd->turning - (angleturn[tspeed])); + cmd->turning -= KART_FULLTURN; } else if (turnleft && !(turnright)) { - cmd->turning = (INT16)(cmd->turning + (angleturn[tspeed])); + cmd->turning += KART_FULLTURN; } if (analogjoystickmove && joystickvector.xaxis != 0) { - cmd->turning = (INT16)(cmd->turning - (((joystickvector.xaxis * angleturn[0]) >> 10))); + cmd->turning -= (joystickvector.xaxis * KART_FULLTURN) >> 10; } // Specator mouse turning if (player->spectator) { - cmd->turning = (INT16)(cmd->turning - ((mousex*(encoremode ? -1 : 1)*8))); + cmd->turning -= (mousex * 8) * (encoremode ? -1 : 1); } if (player->spectator || objectplacing) // SRB2Kart: spectators need special controls @@ -1050,6 +1036,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) if (PlayerInputDown(ssplayer, gc_drift) || (usejoystick && axis > 0)) cmd->buttons |= BT_DRIFT; + // Spindash with any button/key + // Simply holds all of the inputs for you. + axis = PlayerJoyAxis(ssplayer, AXISSPINDASH); + if (PlayerInputDown(ssplayer, gc_spindash) || (usejoystick && axis > 0)) + cmd->buttons |= (BT_ACCELERATE|BT_BRAKE|BT_DRIFT); + // rear view with any button/key axis = PlayerJoyAxis(ssplayer, AXISLOOKBACK); if (PlayerInputDown(ssplayer, gc_lookback) || (usejoystick && axis > 0)) @@ -1120,7 +1112,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) cmd->forwardmove += (SINT8)forward; - cmd->latency = modeattacking ? 0 : (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations + cmd->latency = (leveltime & 0xFF); // Send leveltime when this tic was generated to the server for control lag calculations cmd->flags = 0; if (chat_on || CON_Ready()) @@ -1153,10 +1145,10 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) else if (cmd->forwardmove < -MAXPLMOVE) cmd->forwardmove = -MAXPLMOVE; - if (cmd->turning > (angleturn[0])) - cmd->turning = (angleturn[0]); - else if (cmd->turning < (-angleturn[0])) - cmd->turning = (-angleturn[0]); + if (cmd->turning > KART_FULLTURN) + cmd->turning = KART_FULLTURN; + else if (cmd->turning < -KART_FULLTURN) + cmd->turning = -KART_FULLTURN; // Reset away view if a command is given. if ((cmd->forwardmove || cmd->buttons) diff --git a/src/g_game.h b/src/g_game.h index 3bb5b73f4..9e4ef0159 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -106,6 +106,7 @@ typedef enum AXISFIRE = AXISDIGITAL, AXISDRIFT, + AXISSPINDASH, AXISLOOKBACK, AXISAIM, } axis_input_e; diff --git a/src/g_input.c b/src/g_input.c index 0e10ae8a9..a85219a7e 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -52,11 +52,11 @@ const INT32 gcl_brake[num_gcl_brake] = { gc_brake }; const INT32 gcl_drift[num_gcl_drift] = { gc_drift }; const INT32 gcl_spindash[num_gcl_spindash] = { - gc_accelerate, gc_drift, gc_brake + gc_accelerate, gc_drift, gc_brake, gc_spindash }; const INT32 gcl_movement[num_gcl_movement] = { - gc_accelerate, gc_drift, gc_brake, gc_turnleft, gc_turnright + gc_accelerate, gc_drift, gc_brake, gc_spindash, gc_turnleft, gc_turnright }; const INT32 gcl_item[num_gcl_item] = { @@ -64,7 +64,7 @@ const INT32 gcl_item[num_gcl_item] = { }; const INT32 gcl_full[num_gcl_full] = { - gc_accelerate, gc_drift, gc_brake, gc_turnleft, gc_turnright, + gc_accelerate, gc_drift, gc_brake, gc_spindash, gc_turnleft, gc_turnright, gc_fire, gc_aimforward, gc_aimbackward, gc_lookback }; diff --git a/src/g_input.h b/src/g_input.h index 651f95324..57941d6c1 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -78,6 +78,7 @@ typedef enum gc_accelerate, gc_drift, gc_brake, + gc_spindash, gc_fire, gc_lookback, gc_camreset, @@ -129,10 +130,10 @@ extern INT32 gamecontroldefault[MAXSPLITSCREENPLAYERS][num_gamecontrolschemes][n #define num_gcl_accelerate 1 #define num_gcl_brake 1 #define num_gcl_drift 1 -#define num_gcl_spindash 3 -#define num_gcl_movement 5 +#define num_gcl_spindash 4 +#define num_gcl_movement 6 #define num_gcl_item 3 -#define num_gcl_full 9 +#define num_gcl_full 10 extern const INT32 gcl_accelerate[num_gcl_accelerate]; extern const INT32 gcl_brake[num_gcl_brake]; diff --git a/src/k_bot.c b/src/k_bot.c index 1d7a9bb7b..f6d3a993f 100644 --- a/src/k_bot.c +++ b/src/k_bot.c @@ -572,9 +572,11 @@ static botprediction_t *K_CreateBotPrediction(player_t *player) const tic_t futuresight = (TICRATE * normal) / max(1, handling); // How far ahead into the future to try and predict const fixed_t speed = max(P_AproxDistance(player->mo->momx, player->mo->momy), K_GetKartSpeed(player, false) / 4); - const INT32 distance = (FixedMul(speed, distreduce) / FRACUNIT) * futuresight; - botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); + const INT32 startDist = (768 * mapobjectscale) / FRACUNIT; + const INT32 distance = ((FixedMul(speed, distreduce) / FRACUNIT) * futuresight) + startDist; + + botprediction_t *predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); waypoint_t *wp = player->nextwaypoint; INT32 distanceleft = distance; @@ -840,6 +842,70 @@ static INT16 K_FindBotController(mobj_t *mo) return -1; } +/*-------------------------------------------------- + static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) + + Draws objects to show where the viewpoint bot is trying to go. + + Input Arguments:- + predict - The prediction to visualize. + player - The bot player this prediction is for. + + Return:- + None +--------------------------------------------------*/ +static void K_DrawPredictionDebug(botprediction_t *predict, player_t *player) +{ + mobj_t *debugMobj = NULL; + angle_t sideAngle = ANGLE_MAX; + UINT8 i = UINT8_MAX; + + I_Assert(predict != NULL); + I_Assert(player != NULL); + I_Assert(player->mo != NULL && P_MobjWasRemoved(player->mo) == false); + + sideAngle = player->mo->angle + ANGLE_90; + + debugMobj = P_SpawnMobj(predict->x, predict->y, player->mo->z, MT_SPARK); + P_SetMobjState(debugMobj, S_THOK); + + debugMobj->frame &= ~FF_TRANSMASK; + debugMobj->frame |= FF_TRANS20|FF_FULLBRIGHT; + + debugMobj->color = SKINCOLOR_ORANGE; + debugMobj->scale *= 2; + + debugMobj->tics = 2; + + for (i = 0; i < 2; i++) + { + mobj_t *radiusMobj = NULL; + fixed_t radiusX = predict->x, radiusY = predict->y; + + if (i & 1) + { + radiusX -= FixedMul(predict->radius, FINECOSINE(sideAngle >> ANGLETOFINESHIFT)); + radiusY -= FixedMul(predict->radius, FINESINE(sideAngle >> ANGLETOFINESHIFT)); + } + else + { + radiusX += FixedMul(predict->radius, FINECOSINE(sideAngle >> ANGLETOFINESHIFT)); + radiusY += FixedMul(predict->radius, FINESINE(sideAngle >> ANGLETOFINESHIFT)); + } + + radiusMobj = P_SpawnMobj(radiusX, radiusY, player->mo->z, MT_SPARK); + P_SetMobjState(radiusMobj, S_THOK); + + radiusMobj->frame &= ~FF_TRANSMASK; + radiusMobj->frame |= FF_TRANS20|FF_FULLBRIGHT; + + radiusMobj->color = SKINCOLOR_YELLOW; + radiusMobj->scale /= 2; + + radiusMobj->tics = 2; + } +} + /*-------------------------------------------------- void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) @@ -866,6 +932,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) gamestate != GS_LEVEL || player->mo->scale <= 1 || player->playerstate == PST_DEAD + || leveltime <= introtime ) { // No need to do anything else. @@ -930,7 +997,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) destangle = FixedAngle(sides[controllerLine->sidenum[0]].textureoffset); // Overwritten prediction - predict = Z_Calloc(sizeof(botprediction_t), PU_LEVEL, NULL); + predict = Z_Calloc(sizeof(botprediction_t), PU_STATIC, NULL); predict->x = player->mo->x + FixedMul(dist, FINECOSINE(destangle >> ANGLETOFINESHIFT)); predict->y = player->mo->y + FixedMul(dist, FINESINE(destangle >> ANGLETOFINESHIFT)); @@ -939,6 +1006,9 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) else { predict = K_CreateBotPrediction(player); + + K_NudgePredictionTowardsObjects(predict, player); + destangle = R_PointToAngle2(player->mo->x, player->mo->y, predict->x, predict->y); } @@ -1036,11 +1106,6 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) cmd->forwardmove /= 2; cmd->buttons |= BT_BRAKE; } - else if (dirdist <= realrad) - { - // Steer towards/away from objects! - turnamt += K_BotFindObjects(player, turnamt); - } } } @@ -1056,7 +1121,7 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) finishBeamLine->v1->x, finishBeamLine->v1->y, finishBeamLine->v2->x, finishBeamLine->v2->y, player->mo->x, player->mo->y - ); + ) - player->speed; // Don't run the spindash code at all until we're in the right place trySpindash = false; @@ -1166,6 +1231,11 @@ void K_BuildBotTiccmd(player_t *player, ticcmd_t *cmd) // Free the prediction we made earlier if (predict != NULL) { + if (cv_kartdebugbotpredict.value != 0 && player - players == displayplayers[0]) + { + K_DrawPredictionDebug(predict, player); + } + Z_Free(predict); } } diff --git a/src/k_bot.h b/src/k_bot.h index 2cb1ae460..38408c6af 100644 --- a/src/k_bot.h +++ b/src/k_bot.h @@ -198,19 +198,19 @@ fixed_t K_BotReducePrediction(player_t *player); /*-------------------------------------------------- - INT16 K_BotFindObjects(player_t *player, INT16 turn); + void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player); - Generates a sum for objects to steer towards/away from. + Moves the bot's prediction, based on objects around the bot. Input Arguments:- + predict - The bot's prediction to nudge. player - Player to compare. - turn - Turn value before object steering. Return:- - Turn amount sum to add to final product. + None --------------------------------------------------*/ -INT16 K_BotFindObjects(player_t *player, INT16 turn); +void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player); /*-------------------------------------------------- diff --git a/src/k_botitem.c b/src/k_botitem.c index a871c2305..070f927c8 100644 --- a/src/k_botitem.c +++ b/src/k_botitem.c @@ -909,7 +909,7 @@ static void K_BotItemFlame(player_t *player, ticcmd_t *cmd) --------------------------------------------------*/ static void K_BotItemRings(player_t *player, ticcmd_t *cmd) { - INT32 saferingsval = 16 - K_GetKartRingPower(player); + INT32 saferingsval = 16 - K_GetKartRingPower(player, false); if (player->speed < K_GetKartSpeed(player, false)/2 // Being slowed down too much || player->kartstuff[k_speedboost] > (FRACUNIT/5)) // Have another type of boost (tethering) @@ -971,7 +971,7 @@ void K_BotItemUsage(player_t *player, ticcmd_t *cmd, INT16 turnamt) { // Use rings! - if (!player->exiting) + if (leveltime > starttime && !player->exiting) { K_BotItemRings(player, cmd); } diff --git a/src/k_botsearch.c b/src/k_botsearch.c index 5d6425127..880eb5ef9 100644 --- a/src/k_botsearch.c +++ b/src/k_botsearch.c @@ -31,12 +31,16 @@ struct globalsmuggle { mobj_t *botmo; + botprediction_t *predict; fixed_t distancetocheck; - fixed_t closestlinedist; + INT64 gotoAvgX[2], gotoAvgY[2]; + UINT32 gotoObjs[2]; - INT16 curturn; - INT16 steer; + INT64 avoidAvgX[2], avoidAvgY[2]; + UINT32 avoidObjs[2]; + + fixed_t closestlinedist; fixed_t eggboxx, eggboxy; UINT8 randomitems; @@ -383,7 +387,7 @@ fixed_t K_BotReducePrediction(player_t *player) INT32 xl, xh, yl, yh, bx, by; globalsmuggle.botmo = player->mo; - globalsmuggle.distancetocheck = (player->mo->radius * 16); + globalsmuggle.distancetocheck = (player->mo->radius * 32); globalsmuggle.closestlinedist = INT32_MAX; tmx = player->mo->x; @@ -415,87 +419,107 @@ fixed_t K_BotReducePrediction(player_t *player) return FRACUNIT; } - return FixedDiv(globalsmuggle.closestlinedist, globalsmuggle.distancetocheck); + return (FRACUNIT/2) + (FixedDiv(globalsmuggle.closestlinedist, globalsmuggle.distancetocheck) / 2); } /*-------------------------------------------------- - static void K_SteerFromObject(mobj_t *bot, mobj_t *thing, fixed_t fulldist, fixed_t xdist, boolean towards, INT16 amount) + static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) - Handles steering away/towards the specified object. + Adds an object to the list that the bot wants to go towards. Input Arguments:- - bot - Bot's mobj. - thing - Mobj to steer towards/away from. - fulldist - Distance away from object. - xdist - Horizontal distance away from object. - towards - If true, steer towards the object. Otherwise, steer away. - amount - How hard to turn. + thing - Object to move towards. + side - Which side -- 0 for left, 1 for right + weight - How important this object is. Return:- None --------------------------------------------------*/ -static void K_SteerFromObject(mobj_t *bot, mobj_t *thing, fixed_t fulldist, fixed_t xdist, boolean towards, INT16 amount) +static void K_AddAttackObject(mobj_t *thing, UINT8 side, UINT8 weight) { - angle_t destangle = R_PointToAngle2(bot->x, bot->y, thing->x, thing->y); - angle_t angle; - SINT8 flip = 1; + UINT8 i; - amount = (amount * FixedDiv(globalsmuggle.distancetocheck - fulldist, globalsmuggle.distancetocheck)) / FRACUNIT; + I_Assert(side <= 1); - if (amount == 0) + if (weight == 0) { - // Shouldn't happen return; } - if (towards) + for (i = 0; i < weight; i++) { - if (xdist < FixedHypot(bot->radius, thing->radius)) - { - // Don't need to turn any harder! - - if (abs(globalsmuggle.steer) <= amount) - { - globalsmuggle.steer = 0; - } - else - { - if (globalsmuggle.steer > 0) - { - globalsmuggle.steer -= amount; - } - else if (globalsmuggle.steer < 0) - { - globalsmuggle.steer += amount; - } - } - - return; - } - - // Still turning towards it, flip. - flip = -flip; + globalsmuggle.gotoAvgX[side] += thing->x / mapobjectscale; + globalsmuggle.gotoAvgY[side] += thing->y / mapobjectscale; + globalsmuggle.gotoObjs[side]++; } - - angle = (bot->angle - destangle); - if (angle < ANGLE_180) - { - flip = -flip; - } - - // If going in the opposite direction of where you wanted to turn, - // then reduce the amount that you can turn in that direction. - if ((flip == 1 && globalsmuggle.curturn < 0) - || (flip == -1 && globalsmuggle.curturn > 0)) - { - amount /= 4; - } - - globalsmuggle.steer += amount * flip; } /*-------------------------------------------------- - static boolean K_BotSteerObjects(mobj_t *thing) + static void K_AddDodgeObject(mobj_t *thing, UINT8 side, UINT8 weight) + + Adds an object to the list that the bot wants to dodge. + + Input Arguments:- + thing - Object to move away from. + side - Which side -- 0 for left, 1 for right + weight - How important this object is. + + Return:- + None +--------------------------------------------------*/ +static void K_AddDodgeObject(mobj_t *thing, UINT8 side, UINT8 weight) +{ + UINT8 i; + + I_Assert(side <= 1); + + if (weight == 0) + { + return; + } + + for (i = 0; i < weight; i++) + { + globalsmuggle.gotoAvgX[side] += thing->x / mapobjectscale; + globalsmuggle.gotoAvgY[side] += thing->y / mapobjectscale; + globalsmuggle.gotoObjs[side]++; + } +} + +/*-------------------------------------------------- + static boolean K_PlayerAttackSteer(mobj_t *thing, UINT8 side, UINT8 weight, boolean attackCond, boolean dodgeCond) + + Checks two conditions to determine if the object should be + attacked or dodged. + + Input Arguments:- + thing - Object to move towards/away from. + side - Which side -- 0 for left, 1 for right + weight - How important this object is. + attackCond - If this is true, and dodgeCond isn't, then we go towards the object. + dodgeCond - If this is true, and attackCond isn't, then we move away from the object. + + Return:- + true if either condition is successful. +--------------------------------------------------*/ +static boolean K_PlayerAttackSteer(mobj_t *thing, UINT8 side, UINT8 weight, boolean attackCond, boolean dodgeCond) +{ + if (attackCond == true && dodgeCond == false) + { + K_AddAttackObject(thing, side, weight); + return true; + } + else if (dodgeCond == true && attackCond == false) + { + K_AddDodgeObject(thing, side, weight); + return true; + } + + return false; +} + +/*-------------------------------------------------- + static boolean K_FindObjectsForNudging(mobj_t *thing) Blockmap search function. Finds objects around the bot to steer towards/away from. @@ -506,20 +530,19 @@ static void K_SteerFromObject(mobj_t *bot, mobj_t *thing, fixed_t fulldist, fixe Return:- true continues searching, false ends the search early. --------------------------------------------------*/ -static boolean K_BotSteerObjects(mobj_t *thing) +static boolean K_FindObjectsForNudging(mobj_t *thing) { INT16 anglediff; - fixed_t xdist, ydist, fulldist; - angle_t destangle, angle; - INT16 attack = ((9 - globalsmuggle.botmo->player->kartspeed) * KART_FULLTURN) / 8; // Acceleration chars are more aggressive - INT16 dodge = ((9 - globalsmuggle.botmo->player->kartweight) * KART_FULLTURN) / 8; // Handling chars dodge better + fixed_t fulldist; + angle_t destangle, angle, predictangle; + UINT8 side = 0; if (!globalsmuggle.botmo || P_MobjWasRemoved(globalsmuggle.botmo) || !globalsmuggle.botmo->player) { return false; } - if (!thing->health) + if (thing->health <= 0) { return true; } @@ -529,32 +552,21 @@ static boolean K_BotSteerObjects(mobj_t *thing) return true; } - xdist = K_DistanceOfLineFromPoint( - globalsmuggle.botmo->x, globalsmuggle.botmo->y, - globalsmuggle.botmo->x + FINECOSINE(globalsmuggle.botmo->angle >> ANGLETOFINESHIFT), globalsmuggle.botmo->y + FINESINE(globalsmuggle.botmo->angle >> ANGLETOFINESHIFT), - thing->x, thing->y - ) / 2; // weight x dist more heavily than y dist - - ydist = K_DistanceOfLineFromPoint( - globalsmuggle.botmo->x, globalsmuggle.botmo->y, - globalsmuggle.botmo->x + FINECOSINE((globalsmuggle.botmo->angle + ANGLE_90) >> ANGLETOFINESHIFT), globalsmuggle.botmo->y + FINESINE((globalsmuggle.botmo->angle + ANGLE_90) >> ANGLETOFINESHIFT), - thing->x, thing->y - ); - - fulldist = FixedHypot(xdist, ydist); + fulldist = R_PointToDist2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y) - thing->radius; if (fulldist > globalsmuggle.distancetocheck) { return true; } - if (!P_CheckSight(globalsmuggle.botmo, thing)) + if (P_CheckSight(globalsmuggle.botmo, thing) == false) { return true; } + predictangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, globalsmuggle.predict->x, globalsmuggle.predict->y); destangle = R_PointToAngle2(globalsmuggle.botmo->x, globalsmuggle.botmo->y, thing->x, thing->y); - angle = (globalsmuggle.botmo->angle - destangle); + angle = (predictangle - destangle); if (angle < ANGLE_180) { @@ -563,20 +575,11 @@ static boolean K_BotSteerObjects(mobj_t *thing) else { anglediff = 360-(AngleFixed(angle)>>FRACBITS); + side = 1; } anglediff = abs(anglediff); -#define PlayerAttackSteer(botcond, thingcond) \ - if ((botcond) && !(thingcond)) \ - { \ - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, 2 * (KART_FULLTURN + attack)); \ - } \ - else if ((thingcond) && !(botcond)) \ - { \ - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge)); \ - } - switch (thing->type) { case MT_BANANA: @@ -593,21 +596,21 @@ static boolean K_BotSteerObjects(mobj_t *thing) case MT_BALLHOG: case MT_SPB: case MT_BUBBLESHIELDTRAP: - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge)); + K_AddDodgeObject(thing, side, 20); break; case MT_RANDOMITEM: - if (anglediff >= 60) + if (anglediff >= 45) { break; } if (P_CanPickupItem(globalsmuggle.botmo->player, 1)) { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, KART_FULLTURN + attack); + K_AddAttackObject(thing, side, 10); } break; case MT_EGGMANITEM: - if (anglediff >= 60) + if (anglediff >= 45) { break; } @@ -619,28 +622,28 @@ static boolean K_BotSteerObjects(mobj_t *thing) if (stealth >= requiredstealth) { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, 2 * (KART_FULLTURN + attack)); + K_AddAttackObject(thing, side, 10); } else { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge)); + K_AddDodgeObject(thing, side, 10); } } break; case MT_FLOATINGITEM: - if (anglediff >= 60) + if (anglediff >= 45) { break; } if (P_CanPickupItem(globalsmuggle.botmo->player, 3)) { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, KART_FULLTURN + attack); + K_AddAttackObject(thing, side, 20); } break; case MT_RING: case MT_FLINGRING: - if (anglediff >= 60) + if (anglediff >= 45) { break; } @@ -650,11 +653,7 @@ static boolean K_BotSteerObjects(mobj_t *thing) && !thing->extravalue1 && (globalsmuggle.botmo->player->kartstuff[k_itemtype] != KITEM_THUNDERSHIELD)) { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, - (RINGTOTAL(globalsmuggle.botmo->player) < 3 - ? (4 * (KART_FULLTURN + attack)) - : (KART_FULLTURN + attack)) - ); + K_AddAttackObject(thing, side, (RINGTOTAL(globalsmuggle.botmo->player) < 3) ? 5 : 1); } break; case MT_PLAYER: @@ -664,40 +663,61 @@ static boolean K_BotSteerObjects(mobj_t *thing) { // There REALLY ought to be a better way to handle this logic, right?! // Squishing - PlayerAttackSteer( + if (K_PlayerAttackSteer(thing, side, 20, globalsmuggle.botmo->scale > thing->scale + (mapobjectscale/8), thing->scale > globalsmuggle.botmo->scale + (mapobjectscale/8) - ) + )) + { + break; + } // Invincibility - else PlayerAttackSteer( + else if (K_PlayerAttackSteer(thing, side, 20, globalsmuggle.botmo->player->kartstuff[k_invincibilitytimer], thing->player->kartstuff[k_invincibilitytimer] - ) + )) + { + break; + } // Thunder Shield - else PlayerAttackSteer( + else if (K_PlayerAttackSteer(thing, side, 20, globalsmuggle.botmo->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD, thing->player->kartstuff[k_itemtype] == KITEM_THUNDERSHIELD - ) + )) + { + break; + } // Bubble Shield - else PlayerAttackSteer( + else if (K_PlayerAttackSteer(thing, side, 20, globalsmuggle.botmo->player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD, thing->player->kartstuff[k_itemtype] == KITEM_BUBBLESHIELD - ) + )) + { + break; + } // Flame Shield - else PlayerAttackSteer( + else if (K_PlayerAttackSteer(thing, side, 20, globalsmuggle.botmo->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD, thing->player->kartstuff[k_itemtype] == KITEM_FLAMESHIELD - ) + )) + { + break; + } // Has held item shield - else PlayerAttackSteer( + else if (K_PlayerAttackSteer(thing, side, 20, (globalsmuggle.botmo->player->kartstuff[k_itemheld] || globalsmuggle.botmo->player->kartstuff[k_eggmanheld]), (thing->player->kartstuff[k_itemheld] || thing->player->kartstuff[k_eggmanheld]) - ) + )) + { + break; + } // Ring Sting - else PlayerAttackSteer( + else if (K_PlayerAttackSteer(thing, side, 20, thing->player->rings <= 0, globalsmuggle.botmo->player->rings <= 0 - ) + )) + { + break; + } else { // After ALL of that, we can do standard bumping @@ -716,33 +736,43 @@ static boolean K_BotSteerObjects(mobj_t *thing) if (weightdiff > mapobjectscale) { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, KART_FULLTURN + attack); + K_AddAttackObject(thing, side, 20); } else { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, KART_FULLTURN + dodge); + K_AddDodgeObject(thing, side, 20); } } } break; case MT_BOTHINT: - if (anglediff >= 60) + if (anglediff >= 45) { break; } + else + { + UINT8 weight = 20; - if (thing->extravalue1 == 0) - { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, thing->extravalue2 * (KART_FULLTURN + dodge)); - } - { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, true, thing->extravalue2 * (KART_FULLTURN + attack)); + if (thing->extravalue2 > 0) + { + weight = thing->extravalue2 * 5; + } + + if (thing->extravalue1 == 0) + { + K_AddDodgeObject(thing, side, weight); + } + else + { + K_AddAttackObject(thing, side, weight); + } } break; default: if (thing->flags & (MF_SOLID|MF_ENEMY|MF_BOSS|MF_PAIN|MF_MISSILE)) { - K_SteerFromObject(globalsmuggle.botmo, thing, fulldist, xdist, false, 2 * (KART_FULLTURN + dodge)); + K_AddDodgeObject(thing, side, 20); } break; } @@ -751,18 +781,40 @@ static boolean K_BotSteerObjects(mobj_t *thing) } /*-------------------------------------------------- - INT16 K_BotFindObjects(player_t *player, INT16 turn) + void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) See header file for description. --------------------------------------------------*/ -INT16 K_BotFindObjects(player_t *player, INT16 turn) +void K_NudgePredictionTowardsObjects(botprediction_t *predict, player_t *player) { INT32 xl, xh, yl, yh, bx, by; - globalsmuggle.steer = 0; + fixed_t distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); + + fixed_t avgX = 0, avgY = 0; + fixed_t avgDist = 0; + + const fixed_t baseNudge = 128 * mapobjectscale; + fixed_t maxNudge = distToPredict; + fixed_t nudgeDist = 0; + angle_t nudgeDir = 0; + + SINT8 gotoSide = -1; + UINT8 i; + globalsmuggle.botmo = player->mo; - globalsmuggle.curturn = turn; - globalsmuggle.distancetocheck = (player->mo->radius * 32) + (player->speed * 4); + globalsmuggle.predict = predict; + + globalsmuggle.distancetocheck = distToPredict; + + for (i = 0; i < 2; i++) + { + globalsmuggle.gotoAvgX[i] = globalsmuggle.gotoAvgY[i] = 0; + globalsmuggle.gotoObjs[i] = 0; + + globalsmuggle.avoidAvgX[i] = globalsmuggle.avoidAvgY[i] = 0; + globalsmuggle.avoidObjs[i] = 0; + } xl = (unsigned)(globalsmuggle.botmo->x - globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; xh = (unsigned)(globalsmuggle.botmo->x + globalsmuggle.distancetocheck - bmaporgx)>>MAPBLOCKSHIFT; @@ -775,9 +827,120 @@ INT16 K_BotFindObjects(player_t *player, INT16 turn) { for (by = yl; by <= yh; by++) { - P_BlockThingsIterator(bx, by, K_BotSteerObjects); + P_BlockThingsIterator(bx, by, K_FindObjectsForNudging); } } - return globalsmuggle.steer; + // Handle dodge characters + if (globalsmuggle.avoidObjs[1] > 0 || globalsmuggle.avoidObjs[0] > 0) + { + if (globalsmuggle.avoidObjs[1] > globalsmuggle.avoidObjs[0]) + { + gotoSide = 1; + } + else + { + gotoSide = 0; + } + + avgX = (globalsmuggle.avoidAvgX[gotoSide] / globalsmuggle.avoidObjs[gotoSide]) * mapobjectscale; + avgY = (globalsmuggle.avoidAvgY[gotoSide] / globalsmuggle.avoidObjs[gotoSide]) * mapobjectscale; + + avgDist = R_PointToDist2( + avgX, avgY, + predict->x, predict->y + ); + + // High handling characters dodge better + nudgeDist = ((9 - globalsmuggle.botmo->player->kartweight) + 1) * baseNudge; + + maxNudge = max(distToPredict - predict->radius, predict->radius); + if (nudgeDist > maxNudge) + { + nudgeDist = maxNudge; + } + + // Point away + nudgeDir = R_PointToAngle2( + avgX, avgY, + predict->x, predict->y + ); + + predict->x += FixedMul(nudgeDist, FINECOSINE(nudgeDir >> ANGLETOFINESHIFT)); + predict->y += FixedMul(nudgeDist, FINESINE(nudgeDir >> ANGLETOFINESHIFT)); + + distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); + + // Flip side, since we want to check for objects to steer towards on the side we're NOT dodging. + if (gotoSide == 0) + { + gotoSide = 1; + } + else + { + gotoSide = 0; + } + } + + if (gotoSide == -1) + { + // Pick a side here if there were no objects to dodge. + // We don't want to pick contradictory sides, so keep the old side otherwise, + // even if there's more to grab on the other side. + + if (globalsmuggle.gotoObjs[1] > globalsmuggle.gotoObjs[0]) + { + gotoSide = 1; + } + else + { + gotoSide = 0; + } + } + + // Check if our side is invalid, if so, don't do the code below. + if (gotoSide != -1 && globalsmuggle.gotoObjs[gotoSide] == 0) + { + // Do not use a side + gotoSide = -1; + } + + if (gotoSide != -1) + { + avgX = (globalsmuggle.gotoAvgX[gotoSide] / globalsmuggle.gotoObjs[gotoSide]) * mapobjectscale; + avgY = (globalsmuggle.gotoAvgY[gotoSide] / globalsmuggle.gotoObjs[gotoSide]) * mapobjectscale; + + avgDist = R_PointToDist2( + predict->x, predict->y, + avgX, avgY + ); + + // Acceleration characters are more aggressive + nudgeDist = ((9 - globalsmuggle.botmo->player->kartspeed) + 1) * baseNudge; + + maxNudge = max(distToPredict - predict->radius, predict->radius); + if (nudgeDist > maxNudge) + { + nudgeDist = maxNudge; + } + + if (avgDist <= nudgeDist) + { + predict->x = avgX; + predict->y = avgY; + } + else + { + // Point towards + nudgeDir = R_PointToAngle2( + predict->x, predict->y, + avgX, avgY + ); + + predict->x += FixedMul(nudgeDist, FINECOSINE(nudgeDir >> ANGLETOFINESHIFT)); + predict->y += FixedMul(nudgeDist, FINESINE(nudgeDir >> ANGLETOFINESHIFT)); + + //distToPredict = R_PointToDist2(player->mo->x, player->mo->y, predict->x, predict->y); + } + } } diff --git a/src/k_kart.c b/src/k_kart.c index da9493976..fb899360a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -252,6 +252,7 @@ void K_RegisterKartStuff(void) CV_RegisterVar(&cv_kartdebugdistribution); CV_RegisterVar(&cv_kartdebughuddrop); CV_RegisterVar(&cv_kartdebugwaypoints); + CV_RegisterVar(&cv_kartdebugbotpredict); CV_RegisterVar(&cv_kartdebugcheckpoint); CV_RegisterVar(&cv_kartdebugnodes); @@ -6935,11 +6936,11 @@ void K_UpdateDistanceFromFinishLine(player_t *const player) } } -INT32 K_GetKartRingPower(player_t *player) +INT32 K_GetKartRingPower(player_t *player, boolean boosted) { INT32 ringPower = ((9 - player->kartspeed) + (9 - player->kartweight)) / 2; - if (K_PlayerUsesBotMovement(player)) + if (boosted == true && K_PlayerUsesBotMovement(player)) { // Double for Lv. 9 ringPower += (player->botvars.difficulty * ringPower) / MAXBOTDIFFICULTY; diff --git a/src/k_kart.h b/src/k_kart.h index 10c166890..da40df761 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -69,7 +69,7 @@ void K_UpdateHnextList(player_t *player, boolean clean); void K_DropHnextList(player_t *player, boolean keepshields); void K_RepairOrbitChain(mobj_t *orbit); player_t *K_FindJawzTarget(mobj_t *actor, player_t *source); -INT32 K_GetKartRingPower(player_t *player); +INT32 K_GetKartRingPower(player_t *player, boolean boosted); void K_UpdateDistanceFromFinishLine(player_t *const player); boolean K_CheckPlayersRespawnColliding(INT32 playernum, fixed_t x, fixed_t y); INT16 K_GetKartTurnValue(player_t *player, INT16 turnvalue); diff --git a/src/k_waypoint.c b/src/k_waypoint.c index ae6841a34..73eb82bfa 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -535,9 +535,9 @@ static void K_DebugWaypointsSpawnLine(waypoint_t *const waypoint1, waypoint_t *c { spawnedmobj = P_SpawnMobj(x, y, z, MT_SPARK); P_SetMobjState(spawnedmobj, S_THOK); - spawnedmobj->state->nextstate = S_NULL; - spawnedmobj->state->tics = 1; - spawnedmobj->frame = spawnedmobj->frame & ~FF_TRANSMASK; + spawnedmobj->tics = 1; + spawnedmobj->frame &= ~FF_TRANSMASK; + spawnedmobj->frame |= FF_FULLBRIGHT; spawnedmobj->color = linkcolour; spawnedmobj->scale = FixedMul(spawnedmobj->scale, FixedMul(FRACUNIT/4, FixedDiv((15 - ((leveltime + n) % 16))*FRACUNIT, 15*FRACUNIT))); } @@ -582,9 +582,9 @@ static void K_DebugWaypointDrawRadius(waypoint_t *const waypoint) radiusOrb = P_SpawnMobj(spawnX, spawnY, spawnZ, MT_SPARK); P_SetMobjState(radiusOrb, S_THOK); - radiusOrb->state->nextstate = S_NULL; - radiusOrb->state->tics = 1; - radiusOrb->frame = radiusOrb->frame & ~FF_TRANSMASK; + radiusOrb->tics = 1; + radiusOrb->frame &= ~FF_TRANSMASK; + radiusOrb->frame |= FF_FULLBRIGHT; radiusOrb->color = SKINCOLOR_PURPLE; radiusOrb->scale = radiusOrb->scale / 4; } @@ -623,7 +623,7 @@ void K_DebugWaypointsVisualise(void) P_SetMobjState(debugmobj, S_THOK); debugmobj->frame &= ~FF_TRANSMASK; - debugmobj->frame |= FF_TRANS20; + debugmobj->frame |= FF_TRANS20|FF_FULLBRIGHT; // There's a waypoint setup for this mobj! So draw that it's a valid waypoint and draw lines to its connections if (waypoint != NULL) @@ -683,8 +683,7 @@ void K_DebugWaypointsVisualise(void) { debugmobj->color = SKINCOLOR_RED; } - debugmobj->state->tics = 1; - debugmobj->state->nextstate = S_NULL; + debugmobj->tics = 1; } } diff --git a/src/m_menu.c b/src/m_menu.c index 9ac24aee1..150b64d9c 100644 --- a/src/m_menu.c +++ b/src/m_menu.c @@ -1142,6 +1142,7 @@ static menuitem_t OP_AllControlsMenu[] = {IT_CONTROL, NULL, "Turn Right", M_ChangeControl, gc_turnright }, {IT_CONTROL, NULL, "Drift", M_ChangeControl, gc_drift }, {IT_CONTROL, NULL, "Brake", M_ChangeControl, gc_brake }, + {IT_CONTROL, NULL, "Spindash", M_ChangeControl, gc_spindash }, {IT_CONTROL, NULL, "Use/Throw Item", M_ChangeControl, gc_fire }, {IT_CONTROL, NULL, "Aim Forward", M_ChangeControl, gc_aimforward }, {IT_CONTROL, NULL, "Aim Backward", M_ChangeControl, gc_aimbackward}, @@ -2703,8 +2704,8 @@ boolean M_Responder(event_t *ev) M_QuitSRB2(0); return true; - case KEY_F11: // Gamma Level - CV_AddValue(&cv_globalgamma, 1); + case KEY_F11: // Fullscreen + CV_AddValue(&cv_fullscreen, 1); return true; // Spymode on F12 handled in game logic @@ -6146,7 +6147,6 @@ static void M_PlaybackToggleFreecam(INT32 choice) demo.freecam = false; // reset democam vars: democam.cam = NULL; - democam.turnheld = false; democam.keyboardlook = false; // reset only these. localangle / aiming gets set before the cam does anything anyway } } @@ -10404,22 +10404,22 @@ static void M_Setup1PControlsMenu(INT32 choice) OP_AllControlsMenu[0].itemaction = &OP_Joystick1Def; // Unhide P1-only controls - OP_AllControlsMenu[15].status = IT_CONTROL; // Chat - //OP_AllControlsMenu[16].status = IT_CONTROL; // Team-chat - OP_AllControlsMenu[16].status = IT_CONTROL; // Rankings - //OP_AllControlsMenu[17].status = IT_CONTROL; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_CONTROL; // Pause - OP_AllControlsMenu[21].status = IT_CONTROL; // Screenshot - OP_AllControlsMenu[22].status = IT_CONTROL; // GIF - OP_AllControlsMenu[23].status = IT_CONTROL; // System Menu - OP_AllControlsMenu[24].status = IT_CONTROL; // Console - /*OP_AllControlsMenu[25].status = IT_HEADER; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_SPACE; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_CONTROL; // Spectate - OP_AllControlsMenu[28].status = IT_CONTROL; // Look Up - OP_AllControlsMenu[29].status = IT_CONTROL; // Look Down - OP_AllControlsMenu[30].status = IT_CONTROL; // Center View + OP_AllControlsMenu[16].status = IT_CONTROL; // Chat + //OP_AllControlsMenu[17].status = IT_CONTROL; // Team-chat + OP_AllControlsMenu[17].status = IT_CONTROL; // Rankings + //OP_AllControlsMenu[18].status = IT_CONTROL; // Viewpoint + // 19 is Reset Camera, 20 is Toggle Chasecam + OP_AllControlsMenu[21].status = IT_CONTROL; // Pause + OP_AllControlsMenu[22].status = IT_CONTROL; // Screenshot + OP_AllControlsMenu[23].status = IT_CONTROL; // GIF + OP_AllControlsMenu[24].status = IT_CONTROL; // System Menu + OP_AllControlsMenu[25].status = IT_CONTROL; // Console + /*OP_AllControlsMenu[26].status = IT_HEADER; // Spectator Controls header + OP_AllControlsMenu[27].status = IT_SPACE; // Spectator Controls space + OP_AllControlsMenu[28].status = IT_CONTROL; // Spectate + OP_AllControlsMenu[29].status = IT_CONTROL; // Look Up + OP_AllControlsMenu[30].status = IT_CONTROL; // Look Down + OP_AllControlsMenu[31].status = IT_CONTROL; // Center View */ M_SetupNextMenu(&OP_AllControlsDef); @@ -10436,22 +10436,22 @@ static void M_Setup2PControlsMenu(INT32 choice) OP_AllControlsMenu[0].itemaction = &OP_Joystick2Def; // Hide P1-only controls - OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat - //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat - OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console - /*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectate - OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Look Up - OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Down - OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Center View + OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Chat + //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Team-chat + OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Rankings + //OP_AllControlsMenu[18].status = IT_GRAYEDOUT2; // Viewpoint + // 19 is Reset Camera, 20 is Toggle Chasecam + OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Pause + OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // Screenshot + OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // GIF + OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // System Menu + OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Console + /*OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls header + OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectator Controls space + OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Spectate + OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Up + OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Look Down + OP_AllControlsMenu[31].status = IT_GRAYEDOUT2; // Center View */ M_SetupNextMenu(&OP_AllControlsDef); @@ -10468,22 +10468,22 @@ static void M_Setup3PControlsMenu(INT32 choice) OP_AllControlsMenu[0].itemaction = &OP_Joystick3Def; // Hide P1-only controls - OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat - //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat - OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console - /*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectate - OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Look Up - OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Down - OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Center View + OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Chat + //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Team-chat + OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Rankings + //OP_AllControlsMenu[18].status = IT_GRAYEDOUT2; // Viewpoint + // 19 is Reset Camera, 20 is Toggle Chasecam + OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Pause + OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // Screenshot + OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // GIF + OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // System Menu + OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Console + /*OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls header + OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectator Controls space + OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Spectate + OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Up + OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Look Down + OP_AllControlsMenu[31].status = IT_GRAYEDOUT2; // Center View */ M_SetupNextMenu(&OP_AllControlsDef); @@ -10500,22 +10500,22 @@ static void M_Setup4PControlsMenu(INT32 choice) OP_AllControlsMenu[0].itemaction = &OP_Joystick4Def; // Hide P1-only controls - OP_AllControlsMenu[15].status = IT_GRAYEDOUT2; // Chat - //OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Team-chat - OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Rankings - //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Viewpoint - // 18 is Reset Camera, 19 is Toggle Chasecam - OP_AllControlsMenu[20].status = IT_GRAYEDOUT2; // Pause - OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Screenshot - OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // GIF - OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // System Menu - OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // Console - /*OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Spectator Controls header - OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls space - OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectate - OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Look Up - OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Down - OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Center View + OP_AllControlsMenu[16].status = IT_GRAYEDOUT2; // Chat + //OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Team-chat + OP_AllControlsMenu[17].status = IT_GRAYEDOUT2; // Rankings + //OP_AllControlsMenu[18].status = IT_GRAYEDOUT2; // Viewpoint + // 19 is Reset Camera, 20 is Toggle Chasecam + OP_AllControlsMenu[21].status = IT_GRAYEDOUT2; // Pause + OP_AllControlsMenu[22].status = IT_GRAYEDOUT2; // Screenshot + OP_AllControlsMenu[23].status = IT_GRAYEDOUT2; // GIF + OP_AllControlsMenu[24].status = IT_GRAYEDOUT2; // System Menu + OP_AllControlsMenu[25].status = IT_GRAYEDOUT2; // Console + /*OP_AllControlsMenu[26].status = IT_GRAYEDOUT2; // Spectator Controls header + OP_AllControlsMenu[27].status = IT_GRAYEDOUT2; // Spectator Controls space + OP_AllControlsMenu[28].status = IT_GRAYEDOUT2; // Spectate + OP_AllControlsMenu[29].status = IT_GRAYEDOUT2; // Look Up + OP_AllControlsMenu[30].status = IT_GRAYEDOUT2; // Look Down + OP_AllControlsMenu[31].status = IT_GRAYEDOUT2; // Center View */ M_SetupNextMenu(&OP_AllControlsDef); diff --git a/src/p_enemy.c b/src/p_enemy.c index 83024f767..266eb212c 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -4172,7 +4172,7 @@ void A_AttractChase(mobj_t *actor) angle_t offset = FixedAngle(18<target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; + actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player, true) + 3; S_StartSound(actor->target, sfx_s1b5); sparkle = P_SpawnMobj(actor->target->x, actor->target->y, actor->target->z, MT_RINGSPARKS); @@ -4200,7 +4200,7 @@ void A_AttractChase(mobj_t *actor) if (actor->extravalue1 >= 16) { if (!P_GivePlayerRings(actor->target->player, 1)) // returns 0 if addition failed - actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player)+3; + actor->target->player->kartstuff[k_ringboost] += K_GetKartRingPower(actor->target->player, true) + 3; if (actor->cvmem) // caching S_StartSound(actor->target, sfx_s1c5); diff --git a/src/p_inter.c b/src/p_inter.c index c66d5d266..257e87e47 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -1863,7 +1863,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (!(target->flags & MF_SHOOTABLE)) return false; // shouldn't happen... - if (target->hitlag > 0) + if (!(damagetype & DMG_DEATHMASK) && target->hitlag > 0) return false; } @@ -1947,7 +1947,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da if (combo == false) { - if (player->powers[pw_flashing] > 0 || player->kartstuff[k_squishedtimer] > 0 || (player->kartstuff[k_spinouttimer] > 0 && player->kartstuff[k_spinouttype] != 2)) + if (player->powers[pw_flashing] > 0) { // Post-hit invincibility K_DoInstashield(player); diff --git a/src/p_mobj.c b/src/p_mobj.c index c43876707..fff2a78f1 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11803,7 +11803,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean // Steering amount if (mthing->args[1] == 0) { - mobj->extravalue2 = 2; + mobj->extravalue2 = 4; } else { diff --git a/src/p_setup.c b/src/p_setup.c index 6f50e4f04..4190f95b6 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1699,7 +1699,7 @@ static void ParseTextmapThingParameter(UINT32 i, char *param, char *val) else if (fastcmp(param, "type")) mapthings[i].type = atol(val); else if (fastcmp(param, "scale") || fastcmp(param, "scalex") || fastcmp(param, "scaley")) - mapthings[i].scale = FLOAT_TO_FIXED(atof(val)); + mapthings[i].scale = FixedMul(mapobjectscale, FLOAT_TO_FIXED(atof(val))); // Flags else if (fastcmp(param, "extra") && fastcmp("true", val)) mapthings[i].options |= MTF_EXTRA; diff --git a/src/p_user.c b/src/p_user.c index 6710ad3cc..09b8865fd 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2776,9 +2776,7 @@ fixed_t t_cam_rotate[MAXSPLITSCREENPLAYERS] = {-42,-42,-42,-42}; // Heavily simplified version of G_BuildTicCmd that only takes the local first player's control input and converts it to readable ticcmd_t // we then throw that ticcmd garbage in the camera and make it move - -// redefine this -static fixed_t angleturn[2] = {KART_FULLTURN, KART_FULLTURN/4}; // + slow turn +// TODO: please just use the normal ticcmd function somehow static ticcmd_t cameracmd; @@ -2792,7 +2790,7 @@ void P_InitCameraCmd(void) static ticcmd_t *P_CameraCmd(camera_t *cam) { - INT32 th, tspeed, forward, axis; //i + INT32 forward, axis; //i // these ones used for multiple conditions boolean turnleft, turnright, mouseaiming; boolean invertmouse, lookaxis, usejoystick, kbl; @@ -2805,7 +2803,6 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) if (!demo.playback) return cmd; // empty cmd, no. - th = democam.turnheld; kbl = democam.keyboardlook; G_CopyTiccmd(cmd, I_BaseTiccmd(), 1); // empty, or external driver @@ -2835,31 +2832,19 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) } forward = 0; - // use two stage accelerative turning - // on the keyboard and joystick - if (turnleft || turnright) - th += 1; - else - th = 0; - - if (th < SLOWTURNTICS) - tspeed = 1; // slow turn - else - tspeed = 0; - cmd->turning = 0; // let movement keys cancel each other out if (turnright && !(turnleft)) { - cmd->turning = (INT16)(cmd->turning - (angleturn[tspeed])); + cmd->turning -= KART_FULLTURN; } else if (turnleft && !(turnright)) { - cmd->turning = (INT16)(cmd->turning + (angleturn[tspeed])); + cmd->turning += KART_FULLTURN; } - cmd->turning = (INT16)(cmd->turning - ((mousex*(encoremode ? -1 : 1)*8))); + cmd->turning -= (mousex * 8) * (encoremode ? -1 : 1); axis = PlayerJoyAxis(1, AXISMOVE); if (PlayerInputDown(1, gc_accelerate) || (usejoystick && axis > 0)) @@ -2917,7 +2902,11 @@ static ticcmd_t *P_CameraCmd(camera_t *cam) else if (cmd->forwardmove < -MAXPLMOVE) cmd->forwardmove = -MAXPLMOVE; - democam.turnheld = th; + if (cmd->turning > KART_FULLTURN) + cmd->turning = KART_FULLTURN; + else if (cmd->turning < -KART_FULLTURN) + cmd->turning = -KART_FULLTURN; + democam.keyboardlook = kbl; return cmd;