Introduce the concept of an "InputContext".

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2949 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
Meep-Eep
2008-03-08 23:00:57 +00:00
parent 244eec1c77
commit f9b0a5c680
26 changed files with 578 additions and 238 deletions
+1
View File
@@ -1,4 +1,5 @@
Changes towards version 0.7:
- Introduce the concept of an "InputContext" - SvdB
- Don't use alloca() in uio. - SvdB
- Replace PlayerOne/PlayerTwo by PlayerControls[0]/PlayerControls[1] - SvdB
- Moved comm resources into starcon.ls2 - Michael
+12
View File
@@ -3848,6 +3848,14 @@ SOURCE=..\sc2code\battle.h
# End Source File
# Begin Source File
SOURCE=..\sc2code\battlecontrols.c
# End Source File
# Begin Source File
SOURCE=..\sc2code\battlecontrols.h
# End Source File
# Begin Source File
SOURCE=..\sc2code\border.c
# End Source File
# Begin Source File
@@ -4304,6 +4312,10 @@ SOURCE=..\sc2code\tactrans.c
# End Source File
# Begin Source File
SOURCE=..\sc2code\tactrans.h
# End Source File
# Begin Source File
SOURCE=..\sc2code\trans.c
# End Source File
# Begin Source File
+10 -11
View File
@@ -1,15 +1,14 @@
uqm_SUBDIRS="comm libs planets ships"
uqm_CFILES="battle.c border.c build.c cleanup.c clock.c cnctdlg.c collide.c
comm.c commanim.c commglue.c confirm.c credits.c cyborg.c
demo.c displist.c dummy.c encount.c flash.c fmv.c galaxy.c gameev.c
gameinp.c gameopt.c gendef.c getchar.c globdata.c gravity.c
gravwell.c grpinfo.c hyper.c init.c intel.c intro.c ipdisp.c
load.c loadmele.c loadship.c master.c melee.c menu.c misc.c
oscill.c outfit.c pickmele.c pickship.c plandata.c process.c
restart.c save.c settings.c setup.c setupmenu.c ship.c
shipstat.c shipyard.c sis.c sounds.c starbase.c starcon.c
starmap.c state.c status.c tactrans.c trans.c uqmdebug.c
util.c velocity.c weapon.c"
uqm_CFILES="battle.c battlecontrols.c border.c build.c cleanup.c clock.c
cnctdlg.c collide.c comm.c commanim.c commglue.c confirm.c credits.c
cyborg.c demo.c displist.c dummy.c encount.c flash.c fmv.c galaxy.c
gameev.c gameinp.c gameopt.c gendef.c getchar.c globdata.c gravity.c
gravwell.c grpinfo.c hyper.c init.c intel.c intro.c ipdisp.c load.c
loadmele.c loadship.c master.c melee.c menu.c misc.c oscill.c
outfit.c pickmele.c pickship.c plandata.c process.c restart.c save.c
settings.c setup.c setupmenu.c ship.c shipstat.c shipyard.c sis.c
sounds.c starbase.c starcon.c starmap.c state.c status.c tactrans.c
trans.c uqmdebug.c util.c velocity.c weapon.c"
if [ -n "$uqm_NETPLAY" ]; then
uqm_SUBDIRS="$uqm_SUBDIRS netplay"
fi
+11 -3
View File
@@ -18,8 +18,8 @@
#include "battle.h"
#include "battlecontrols.h"
#include "controls.h"
#include "options.h"
#include "init.h"
#include "intel.h"
#ifdef NETPLAY
@@ -132,6 +132,13 @@ setupBattleInputOrder(void)
#endif
}
BATTLE_INPUT_STATE
frameInputHuman (HumanInputContext *context, STARSHIP *StarShipPtr)
{
(void) StarShipPtr;
return CurrentInputToBattleInput (context->playerNr);
}
static void
ProcessInput (void)
{
@@ -163,8 +170,9 @@ ProcessInput (void)
{
CyborgDescPtr = StarShipPtr;
InputState = (*(PlayerInput[cur_player]))(cur_player,
StarShipPtr);
InputState = PlayerInput[cur_player]->handlers->frameInput (
PlayerInput[cur_player], StarShipPtr);
#if CREATE_JOURNAL
JournalInput (InputState);
#endif /* CREATE_JOURNAL */
+11 -3
View File
@@ -16,8 +16,15 @@
#ifndef _BATTLE_H
#define _BATTLE_H
#include "options.h"
#include "libs/compiler.h"
#if defined (NETPLAY)
typedef DWORD BattleFrameCounter;
#endif
#include "displist.h"
// for QUEUE
#include "init.h"
// For NUM_SIDES
@@ -35,16 +42,17 @@ extern QUEUE disp_q;
extern BYTE battle_counter[NUM_SIDES];
extern BOOLEAN instantVictory;
#ifdef NETPLAY
typedef DWORD BattleFrameCounter;
#if defined (NETPLAY)
extern BattleFrameCounter battleFrameCount;
#endif
#ifdef NETPLAY
extern COUNT currentDeadSide;
COUNT GetPlayerOrder (COUNT i);
#else
# define GetPlayerOrder(i) (i)
#endif
extern BOOLEAN Battle (void);
BOOLEAN Battle (void);
#endif /* _BATTLE_H */
+98
View File
@@ -0,0 +1,98 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "battlecontrols.h"
#include "intel.h"
// For computer_intelligence()
#include "tactrans.h"
// For battleEndReady*
#include "libs/misc.h"
// For HFree()
#ifdef NETPLAY
# include "netplay/netmelee.h"
#endif /* NETPLAY */
InputContext *PlayerInput[NUM_PLAYERS];
BattleInputHandlers ComputerInputHandlers = {
/* .frameInput = */ (BattleFrameInputFunction) computer_intelligence,
/* .selectShip = */ (SelectShipFunction) selectShipComputer,
/* .battleEndReady = */ (BattleEndReadyFunction) battleEndReadyComputer,
/* .deleteContext = */ InputContext_delete,
};
BattleInputHandlers HumanInputHandlers = {
/* .frameInput = */ (BattleFrameInputFunction) frameInputHuman,
/* .selectShip = */ (SelectShipFunction) selectShipHuman,
/* .battleEndReady = */ (BattleEndReadyFunction) battleEndReadyHuman,
/* .deleteContext = */ InputContext_delete,
};
#ifdef NETPLAY
BattleInputHandlers NetworkInputHandlers = {
/* .frameInput = */ (BattleFrameInputFunction) networkBattleInput,
/* .selectShip = */ (SelectShipFunction) selectShipNetwork,
/* .battleEndReady = */ (BattleEndReadyFunction) battleEndReadyNetwork,
/* .deleteContext = */ InputContext_delete,
};
#endif
void
InputContext_init (InputContext *context, BattleInputHandlers *handlers,
COUNT playerNr)
{
context->handlers = handlers;
context->playerNr = playerNr;
}
void
InputContext_delete (InputContext *context)
{
HFree (context);
}
ComputerInputContext *
ComputerInputContext_new (COUNT playerNr)
{
ComputerInputContext *result = HMalloc (sizeof (ComputerInputContext));
InputContext_init ((InputContext *) result,
&ComputerInputHandlers, playerNr);
return result;
}
HumanInputContext *
HumanInputContext_new (COUNT playerNr)
{
HumanInputContext *result = HMalloc (sizeof (HumanInputContext));
InputContext_init ((InputContext *) result,
&HumanInputHandlers, playerNr);
return result;
}
#ifdef NETPLAY
NetworkInputContext *
NetworkInputContext_new (COUNT playerNr)
{
NetworkInputContext *result = HMalloc (sizeof (NetworkInputContext));
InputContext_init ((InputContext *) result,
&NetworkInputHandlers, playerNr);
return result;
}
#endif
+93
View File
@@ -0,0 +1,93 @@
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _BATTLECONTROLS_H
#define _BATTLECONTROLS_H
typedef struct BattleInputHandlers BattleInputHandlers;
typedef struct InputContext InputContext;
typedef struct ComputerInputContext ComputerInputContext;
typedef struct HumanInputContext HumanInputContext;
#ifdef NETPLAY
typedef struct NetworkInputContext NetworkInputContext;
#endif /* NETPLAY */
#include "controls.h"
#include "pickmele.h"
#include "races.h"
#include "libs/compiler.h"
typedef BATTLE_INPUT_STATE (*BattleFrameInputFunction) (
InputContext *context, STARSHIP *StarShipPtr);
typedef BOOLEAN (*SelectShipFunction) (InputContext *context,
GETMELEE_STATE *gms);
typedef bool (*BattleEndReadyFunction) (InputContext *context);
typedef void (*DeleteInputContextFunction) (InputContext *context);
struct BattleInputHandlers {
BattleFrameInputFunction frameInput;
SelectShipFunction selectShip;
BattleEndReadyFunction battleEndReady;
DeleteInputContextFunction deleteContext;
};
#define INPUT_CONTEXT_COMMON \
BattleInputHandlers *handlers; \
COUNT playerNr;
// Base "class" for all ...InputContext structures
struct InputContext {
INPUT_CONTEXT_COMMON
};
struct ComputerInputContext {
INPUT_CONTEXT_COMMON
// TODO: Put RNG Context used for the AI here.
};
struct HumanInputContext {
INPUT_CONTEXT_COMMON
};
#ifdef NETPLAY
struct NetworkInputContext {
INPUT_CONTEXT_COMMON
// TODO: put NetworkConnection for this player here.
};
#endif /* NETPLAY */
ComputerInputContext *ComputerInputContext_new (COUNT playerNr);
HumanInputContext *HumanInputContext_new (COUNT playerNr);
#ifdef NETPLAY
NetworkInputContext *NetworkInputContext_new (COUNT playerNr);
#endif /* NETPLAY */
extern InputContext *PlayerInput[];
BATTLE_INPUT_STATE frameInputHuman (HumanInputContext *context,
STARSHIP *StarShipPtr);
void InputContext_init(InputContext *context, BattleInputHandlers *handlers,
COUNT playerNr);
void InputContext_delete (InputContext *context);
// Do not call directly, only from the FreeInputContextFunction.
// Call InputContext->handlers->freeContext() to release an
// InputContext.
#endif /* _BATTLECONTROLS_H */
+2 -9
View File
@@ -19,9 +19,6 @@
#ifndef _CONTROLS_H_
#define _CONTROLS_H_
#include "races.h"
// For STARSHIP
#include "libs/compiler.h"
#include "libs/strlib.h"
@@ -89,10 +86,8 @@ typedef UBYTE BATTLE_INPUT_STATE;
#define BATTLE_ESCAPE ((BATTLE_INPUT_STATE)(1 << 5))
#define BATTLE_DOWN ((BATTLE_INPUT_STATE)(1 << 6))
typedef BATTLE_INPUT_STATE (*battle_summary_func) (COUNT player,
STARSHIP *StarShipPtr);
extern battle_summary_func ComputerInput, HumanInput[], NetworkInput;
extern battle_summary_func PlayerInput[];
BATTLE_INPUT_STATE CurrentInputToBattleInput (COUNT player);
BATTLE_INPUT_STATE PulsedInputToBattleInput (COUNT player);
extern CONTROLLER_INPUT_STATE CurrentInputState;
extern CONTROLLER_INPUT_STATE PulsedInputState;
@@ -114,8 +109,6 @@ BOOLEAN ConfirmExit (void);
void DoPopupWindow(const char *msg);
void DoInput (void *pInputState, BOOLEAN resetInput);
BATTLE_INPUT_STATE combat_summary (COUNT player, STARSHIP *StarShipPtr);
extern volatile BOOLEAN GamePaused;
extern volatile BOOLEAN ExitRequested;
+6 -6
View File
@@ -1010,7 +1010,7 @@ Avoid (ELEMENT *ShipPtr, EVALUATE_DESC *EvalDescPtr)
}
BATTLE_INPUT_STATE
tactical_intelligence (COUNT player, STARSHIP *StarShipPtr)
tactical_intelligence (ComputerInputContext *context, STARSHIP *StarShipPtr)
{
ELEMENT *ShipPtr;
ELEMENT Ship;
@@ -1038,7 +1038,7 @@ tactical_intelligence (COUNT player, STARSHIP *StarShipPtr)
ShipMoved = TRUE;
/* Disable ship's special completely for the Standard AI */
if (PlayerControl[player] & STANDARD_RATING)
if (PlayerControl[context->playerNr] & STANDARD_RATING)
++StarShipPtr->special_counter;
#ifdef DEBUG_CYBORG
@@ -1146,9 +1146,9 @@ if (!(ShipPtr->state_flags & FINITE_LIFE)
InitCyborg (EnemyStarShipPtr);
ed.which_turn = WORLD_TO_TURN (
square_root ((long)dx * dx + (long)dy * dy)
);
if (ed.which_turn > ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn)
square_root ((long)dx * dx + (long)dy * dy));
if (ed.which_turn >
ObjectsOfConcern[ENEMY_SHIP_INDEX].which_turn)
{
UnlockElement (hElement);
continue;
@@ -1261,7 +1261,7 @@ if (!(ShipPtr->state_flags & FINITE_LIFE)
ed.which_turn = 0;
}
}
else if (!(PlayerControl[player] & AWESOME_RATING))
else if (!(PlayerControl[context->playerNr] & AWESOME_RATING))
ed.which_turn = 0;
else
{
+7 -2
View File
@@ -19,6 +19,7 @@
#include "encount.h"
#include "battle.h"
#include "battlecontrols.h"
#include "build.h"
#include "colors.h"
#include "controls.h"
@@ -724,6 +725,7 @@ EncounterBattle (void)
RESOURCE_INDEX hLastIndex;
ACTIVITY OldActivity;
extern UWORD nth_frame;
InputContext *savedPlayerInput;
LockMutex (GraphicsLock);
@@ -756,7 +758,9 @@ EncounterBattle (void)
cur_speed = (BYTE)~0; /* maximum speed - no rendering */
nth_frame = MAKE_WORD (1, cur_speed);
PlayerControl[0] = CYBORG_CONTROL | AWESOME_RATING;
PlayerInput[0] = ComputerInput;
savedPlayerInput = PlayerInput[0];
PlayerInput[0] = NULL;
SetPlayerInput (0);
}
GameSounds = CaptureSound (LoadSound (GAME_SOUNDS));
@@ -775,7 +779,8 @@ EncounterBattle (void)
{
nth_frame = MAKE_WORD (0, 0);
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
PlayerInput[0] = HumanInput[0];
ClearPlayerInput (0);
PlayerInput[0] = savedPlayerInput;
}
SetResourceIndex (hResIndex);
+15 -5
View File
@@ -17,18 +17,22 @@
*/
#include "controls.h"
#include "battlecontrols.h"
#include "init.h"
#include "intel.h"
// For computer_intelligence
#ifdef NETPLAY
# include "netplay/netmelee.h"
#endif
#include "planets/planets.h"
#include "settings.h"
#include "sounds.h"
#include "tactrans.h"
#include "libs/inplib.h"
#include "libs/timelib.h"
#include "libs/threadlib.h"
battle_summary_func ComputerInput, HumanInput[NUM_PLAYERS], NetworkInput;
battle_summary_func PlayerInput[NUM_PLAYERS];
#define ACCELERATION_INCREMENT (ONE_SECOND / 12)
#define MENU_REPEAT_DELAY (ONE_SECOND >> 1)
@@ -417,13 +421,19 @@ ControlInputToBattleInput (const int *keyState)
}
BATTLE_INPUT_STATE
combat_summary (COUNT player, STARSHIP *StarShipPtr)
CurrentInputToBattleInput (COUNT player)
{
(void) StarShipPtr;
return ControlInputToBattleInput(
CurrentInputState.key[PlayerControls[player]]);
}
BATTLE_INPUT_STATE
PulsedInputToBattleInput (COUNT player)
{
return ControlInputToBattleInput(
PulsedInputState.key[PlayerControls[player]]);
}
BOOLEAN
AnyButtonPress (BOOLEAN CheckSpecial)
{
+11 -9
View File
@@ -18,6 +18,7 @@
#include "intel.h"
#include "battlecontrols.h"
#include "controls.h"
#include "globdata.h"
#include "setup.h"
@@ -29,7 +30,7 @@
SIZE cur_player;
BATTLE_INPUT_STATE
computer_intelligence (COUNT player, STARSHIP *StarShipPtr)
computer_intelligence (ComputerInputContext *context, STARSHIP *StarShipPtr)
{
BATTLE_INPUT_STATE InputState;
@@ -38,19 +39,20 @@ computer_intelligence (COUNT player, STARSHIP *StarShipPtr)
if (StarShipPtr)
{
if (PlayerControl[player] & CYBORG_CONTROL)
// Selecting the next action for in battle.
if (PlayerControl[context->playerNr] & CYBORG_CONTROL)
{
InputState = tactical_intelligence (player, StarShipPtr);
InputState = tactical_intelligence (context, StarShipPtr);
// allow a player to warp-escape in cyborg mode
if (player == 0)
InputState |= (*(HumanInput[player])) (player, StarShipPtr)
& BATTLE_ESCAPE;
// Allow a player to warp-escape in cyborg mode
if (context->playerNr == 0)
InputState |= CurrentInputToBattleInput (
context->playerNr) & BATTLE_ESCAPE;
}
else
InputState = (*(HumanInput[player])) (player, StarShipPtr);
InputState = CurrentInputToBattleInput (context->playerNr);
}
else if (!(PlayerControl[player] & PSYTRON_CONTROL))
else if (!(PlayerControl[context->playerNr] & PSYTRON_CONTROL))
InputState = 0;
else
{
+6 -4
View File
@@ -19,6 +19,7 @@
#ifndef _INTEL_H
#define _INTEL_H
#include "battlecontrols.h"
#include "controls.h"
#include "element.h"
#include "races.h"
@@ -46,10 +47,10 @@ enum
extern STARSHIP *CyborgDescPtr;
extern SIZE cur_player;
extern BATTLE_INPUT_STATE computer_intelligence (COUNT player,
STARSHIP *StarShipPtr);
extern BATTLE_INPUT_STATE tactical_intelligence (COUNT player,
STARSHIP *StarShipPtr);
extern BATTLE_INPUT_STATE computer_intelligence (
ComputerInputContext *context, STARSHIP *StarShipPtr);
extern BATTLE_INPUT_STATE tactical_intelligence (
ComputerInputContext *context, STARSHIP *StarShipPtr);
extern void ship_intelligence (ELEMENT *ShipPtr,
EVALUATE_DESC *ObjectsOfConcern, COUNT ConcernCounter);
extern BOOLEAN ship_weapons (ELEMENT *ShipPtr, ELEMENT *OtherPtr,
@@ -67,6 +68,7 @@ extern BOOLEAN ThrustShip (ELEMENT *ShipPtr, COUNT angle);
#define PSYTRON_CONTROL (BYTE)(1 << 2)
#define NETWORK_CONTROL (BYTE)(1 << 3)
#define COMPUTER_CONTROL (CYBORG_CONTROL | PSYTRON_CONTROL)
#define CONTROL_MASK (HUMAN_CONTROL | COMPUTER_CONTROL | NETWORK_CONTROL)
#define STANDARD_RATING (BYTE)(1 << 4)
#define GOOD_RATING (BYTE)(1 << 5)
+2 -7
View File
@@ -1714,10 +1714,12 @@ StartMelee (MELEE_STATE *pMS)
WaitForSoundEnd (TFBSOUND_WAIT_ALL);
SetPlayerInputAll ();
load_gravity_well ((BYTE)((COUNT)TFB_Random () %
NUMBER_OF_PLANET_TYPES));
Battle ();
free_gravity_well ();
ClearPlayerInputAll ();
if (GLOBAL (CurrentActivity) & CHECK_ABORT)
return;
@@ -1926,7 +1928,6 @@ DoConnectingDialog (MELEE_STATE *pMS)
{
/* Connection complete! */
PlayerControl[which_side] = NETWORK_CONTROL | STANDARD_RATING;
SetPlayerInput ();
DrawControls (which_side, TRUE);
RedrawMeleeFrame ();
@@ -1975,11 +1976,6 @@ check_for_disconnections (MELEE_STATE *pMS)
}
}
if (changed)
{
SetPlayerInput ();
}
(void) pMS;
}
@@ -2326,7 +2322,6 @@ Melee (void)
PlayerControl[1] = COMPUTER_CONTROL | STANDARD_RATING;
MenuState.SideState[1].TeamImage = MenuState.load.preBuiltList[1];
}
SetPlayerInput ();
teamStringChanged (&MenuState, 0);
teamStringChanged (&MenuState, 1);
entireFleetChanged (&MenuState, 0);
+6 -4
View File
@@ -30,6 +30,8 @@
#include "netplay/proto/ready.h"
#include "netplay/proto/reset.h"
#include "battlecontrols.h"
// for NetworkInputContext
#include "controls.h"
// for BATTLE_INPUT_STATE
#include "init.h"
@@ -318,8 +320,8 @@ setBattleStateConnections(struct battlestate_struct *bs) {
}
BATTLE_INPUT_STATE
networkBattleInput(COUNT player, STARSHIP *StarShipPtr) {
BattleInputBuffer *bib = getBattleInputBuffer(player);
networkBattleInput(NetworkInputContext *context, STARSHIP *StarShipPtr) {
BattleInputBuffer *bib = getBattleInputBuffer(context->playerNr);
BATTLE_INPUT_STATE result;
for (;;) {
@@ -345,7 +347,7 @@ networkBattleInput(COUNT player, STARSHIP *StarShipPtr) {
break;
{
NetConnection *conn = netConnections[player];
NetConnection *conn = netConnections[context->playerNr];
// First try whether there is incoming data, without blocking.
// If there isn't any, only then give a warning, and then
@@ -364,7 +366,7 @@ networkBattleInput(COUNT player, STARSHIP *StarShipPtr) {
#if 0
log_add(log_Warning, "NETPLAY: [%d] stalling for "
"network input. Increase the input delay if this "
"happens a lot.\n", player);
"happens a lot.\n", context->playerNr);
#endif
#define MAX_BLOCK_TIME 500
netInputBlocking(MAX_BLOCK_TIME);
+6 -1
View File
@@ -24,8 +24,12 @@
#include "netconnection.h"
#include "packetsenders.h"
#include "../battlecontrols.h"
// for NetworkInputContext
#include "../controls.h"
// for BATTLE_INPUT_STATE
#include "../races.h"
// for STARSHIP
extern struct NetConnection *netConnections[];
@@ -55,7 +59,8 @@ void sendChecksumConnections(uint32 frameNr, uint32 checksum);
void initBattleStateDataConnections(void);
void setBattleStateConnections(struct battlestate_struct *bs);
BATTLE_INPUT_STATE networkBattleInput(COUNT player, STARSHIP *StarShipPtr);
BATTLE_INPUT_STATE networkBattleInput(NetworkInputContext *context,
STARSHIP *StarShipPtr);
NetConnection *openPlayerNetworkConnection(COUNT player, void *extra);
void closePlayerNetworkConnection(COUNT player);
+106 -124
View File
@@ -16,9 +16,10 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#define PICKMELE_INTERNAL
#include "pickmele.h"
#include "build.h"
#include "battlecontrols.h"
#include "controls.h"
#include "flash.h"
#include "intel.h"
@@ -29,10 +30,8 @@
# include "netplay/notify.h"
#endif
#include "races.h"
#include "settings.h"
#include "setup.h"
#include "sounds.h"
#include "libs/inplib.h"
#include "libs/log.h"
#include "libs/mathlib.h"
@@ -42,33 +41,6 @@
#define PICK_Y_OFFS 24
#define PICK_SIDE_OFFS 100
struct getmelee_struct {
BOOLEAN (*InputFunc) (struct getmelee_struct *pInputState);
COUNT MenuRepeatDelay;
BOOLEAN Initialized;
struct {
TimeCount timeIn;
HSTARSHIP hBattleShip;
// Chosen ship.
COUNT row;
COUNT col;
COUNT ships_left;
// Number of ships still available.
COUNT randomIndex;
// Pre-generated random number.
BOOLEAN selecting;
// Is this player selecting a ship?
BOOLEAN done;
// Has a selection been made for this player?
FlashContext *flashContext;
// Context for controlling the flash rectangle.
#ifdef NETPLAY
BOOLEAN remoteSelected;
#endif
} player[NUM_PLAYERS];
};
#ifdef NETPLAY
static void reportShipSelected (GETMELEE_STATE *gms, COUNT index);
#endif
@@ -146,95 +118,72 @@ PickMelee_ChangedSelection (GETMELEE_STATE *gms, COUNT playerI)
Flash_setRect (gms->player[playerI].flashContext, &r);
}
// Auxiliary function to DoGetMelee for a single player
// Returns FALSE if the player selected abort.
static BOOLEAN
DoGetMeleePlayer (GETMELEE_STATE *gms, COUNT which_player)
// Only returns false when there is no ship for the choice.
bool
setShipSelected(GETMELEE_STATE *gms, COUNT playerI, COUNT choice,
bool reportNetwork)
{
BOOLEAN left, right, up, down, select;
HSTARSHIP ship;
if (PlayerInput[which_player] == ComputerInput)
{
#define COMPUTER_SELECTION_DELAY (ONE_SECOND >> 1)
TimeCount now = GetTimeCounter ();
if (now < gms->player[which_player].timeIn +
COMPUTER_SELECTION_DELAY)
return TRUE;
assert (!gms->player[playerI].done);
left = right = up = down = FALSE;
select = TRUE;
}
#ifdef NETPLAY
else if (PlayerInput[which_player] == NetworkInput)
if (choice == (COUNT) ~0)
{
flushPacketQueues ();
// Sets gms->player[which_player].remoteSelected if input
// is received.
if (gms->player[which_player].remoteSelected)
gms->player[which_player].done = TRUE;
return TRUE;
// Random ship selection.
ship = MeleeShipByUsedIndex (&race_q[playerI],
gms->player[playerI].randomIndex);
}
#endif
else
{
CONTROL_TEMPLATE template;
if (which_player == 0)
template = PlayerControls[0];
else
template = PlayerControls[1];
left = PulsedInputState.key[template][KEY_LEFT];
right = PulsedInputState.key[template][KEY_RIGHT];
up = PulsedInputState.key[template][KEY_UP];
down = PulsedInputState.key[template][KEY_DOWN];
select = PulsedInputState.key[template][KEY_WEAPON];
// Explicit ship selection.
ship = MeleeShipByQueueIndex (&race_q[playerI], choice);
}
if (select)
{
if (gms->player[which_player].col == NUM_MELEE_COLS_ORIG)
{
// Selection is on a non-ship slot. (Random or exit).
if (gms->player[which_player].row == 0)
{
// Random ship
gms->player[which_player].hBattleShip =
MeleeShipByUsedIndex (&race_q[which_player],
gms->player[which_player].randomIndex);
if (ship == 0)
return false;
gms->player[playerI].choice = choice;
gms->player[playerI].hBattleShip = ship;
PlayMenuSound (MENU_SOUND_SUCCESS);
#ifdef NETPLAY
reportShipSelected (gms, (COUNT)~0);
if (reportNetwork)
reportShipSelected (gms, choice);
#else
(void) reportNetwork;
#endif
gms->player[which_player].done = TRUE;
gms->player[playerI].done = true;
return true;
}
// Returns FALSE if aborted.
static BOOLEAN
SelectShip_processInput (GETMELEE_STATE *gms, COUNT playerI,
BATTLE_INPUT_STATE inputState)
{
if (inputState & BATTLE_WEAPON)
{
if (gms->player[playerI].col == NUM_MELEE_COLS_ORIG &&
gms->player[playerI].row == 0)
{
// Random ship
(void) setShipSelected (gms, playerI, (COUNT) ~0, TRUE);
}
else
else if (gms->player[playerI].col == NUM_MELEE_COLS_ORIG &&
gms->player[playerI].row == 1)
{
// Selected exit
if (ConfirmExit ())
return FALSE;
}
}
else
{
// Selection is on a ship slot.
COUNT ship_index;
HSTARSHIP ship;
ship_index = (gms->player[which_player].row * NUM_MELEE_COLS_ORIG)
+ gms->player[which_player].col;
ship = MeleeShipByQueueIndex (&race_q[which_player], ship_index);
if (ship != 0)
{
// Selection contains a ship.
gms->player[which_player].hBattleShip = ship;
gms->player[which_player].done = true;
PlayMenuSound (MENU_SOUND_SUCCESS);
#ifdef NETPLAY
reportShipSelected (gms, ship_index);
#endif
return TRUE;
}
COUNT shipI =
(gms->player[playerI].row * NUM_MELEE_COLS_ORIG)
+ gms->player[playerI].col;
(void) setShipSelected (gms, playerI, shipI, TRUE);
// If the choice is not valid, setShipSelected()
// will not set .done.
}
}
else
@@ -242,43 +191,79 @@ DoGetMeleePlayer (GETMELEE_STATE *gms, COUNT which_player)
// Process motion commands.
COUNT new_row, new_col;
new_row = gms->player[which_player].row;
new_col = gms->player[which_player].col;
if (left)
new_row = gms->player[playerI].row;
new_col = gms->player[playerI].col;
if (inputState & BATTLE_LEFT)
{
if (new_col-- == 0)
new_col = NUM_MELEE_COLS_ORIG;
}
else if (right)
else if (inputState & BATTLE_RIGHT)
{
if (new_col++ == NUM_MELEE_COLS_ORIG)
new_col = 0;
}
if (up)
if (inputState & BATTLE_THRUST)
{
if (new_row-- == 0)
new_row = NUM_MELEE_ROWS - 1;
}
else if (down)
else if (inputState & BATTLE_DOWN)
{
if (++new_row == NUM_MELEE_ROWS)
new_row = 0;
}
if (new_row != gms->player[which_player].row ||
new_col != gms->player[which_player].col)
if (new_row != gms->player[playerI].row ||
new_col != gms->player[playerI].col)
{
gms->player[which_player].row = new_row;
gms->player[which_player].col = new_col;
gms->player[playerI].row = new_row;
gms->player[playerI].col = new_col;
PlayMenuSound (MENU_SOUND_MOVE);
PickMelee_ChangedSelection (gms, which_player);
PickMelee_ChangedSelection (gms, playerI);
}
}
return TRUE;
}
BOOLEAN
selectShipHuman (HumanInputContext *context, GETMELEE_STATE *gms)
{
BATTLE_INPUT_STATE inputState =
PulsedInputToBattleInput (context->playerNr);
return SelectShip_processInput (gms, context->playerNr, inputState);
}
BOOLEAN
selectShipComputer (ComputerInputContext *context, GETMELEE_STATE *gms)
{
#define COMPUTER_SELECTION_DELAY (ONE_SECOND >> 1)
TimeCount now = GetTimeCounter ();
if (now < gms->player[context->playerNr].timeIn +
COMPUTER_SELECTION_DELAY)
return TRUE;
return SelectShip_processInput (gms, context->playerNr, BATTLE_WEAPON);
// Simulate selection of the random choice button.
}
#ifdef NETPLAY
BOOLEAN
selectShipNetwork (NetworkInputContext *context, GETMELEE_STATE *gms)
{
flushPacketQueues ();
// Sets gms->player[context->playerNr].remoteSelected if input
// is received.
if (gms->player[context->playerNr].remoteSelected)
gms->player[context->playerNr].done = TRUE;
return TRUE;
}
#endif
// Select a new ship from the fleet for battle.
// Returns 'TRUE' if no choice has been made yet; this function is to be
// called again later.
@@ -328,7 +313,8 @@ DoGetMelee (GETMELEE_STATE *gms)
continue;
if (!gms->player[playerI].done) {
if (!DoGetMeleePlayer (gms, playerI))
if (!PlayerInput[playerI]->handlers->selectShip (
PlayerInput[playerI], gms))
goto aborted;
if (gms->player[playerI].done)
@@ -351,7 +337,13 @@ aborted:
flushPacketQueues ();
#endif
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
{
if (!gms->player[playerI].selecting)
continue;
gms->player[playerI].choice = 0;
gms->player[playerI].hBattleShip = 0;
}
GLOBAL (CurrentActivity) &= ~CHECK_ABORT;
return FALSE;
}
@@ -591,7 +583,7 @@ GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
Flash_setFrameTime (gmstate.player[playerI].flashContext,
ONE_SECOND / 16);
#ifdef NETPLAY
if (PlayerInput[playerI] == NetworkInput)
if (PlayerControl[playerI] & NETWORK_CONTROL)
Flash_setSpeed (gmstate.player[playerI].flashContext,
ONE_SECOND / 2, 0, ONE_SECOND / 2, 0);
else
@@ -653,6 +645,8 @@ GetMeleeStarShips (COUNT playerMask, HSTARSHIP *ships)
if (!negotiateReadyConnections (true, NetState_interBattle))
ok = false;
}
else
setStateConnections (NetState_interBattle);
#endif
if (!ok)
@@ -745,19 +739,7 @@ updateMeleeSelection (GETMELEE_STATE *gms, COUNT playerI, COUNT ship)
return false;
}
if (ship == (COUNT) ~0)
{
// Random selection.
gms->player[playerI].hBattleShip =
MeleeShipByUsedIndex (&race_q[playerI],
gms->player[playerI].randomIndex);
gms->player[playerI].remoteSelected = TRUE;
return true;
}
gms->player[playerI].hBattleShip =
MeleeShipByQueueIndex (&race_q[playerI], ship);
if (gms->player[playerI].hBattleShip == 0)
if (!setShipSelected (gms, playerI, ship, false))
{
log_add (log_Warning, "Invalid ship selection received from remote "
"party.\n");
+50 -2
View File
@@ -17,7 +17,10 @@
#ifndef _PICKMELE_H
#define _PICKMELE_H
typedef struct getmelee_struct GETMELEE_STATE;
#include "races.h"
#include "battlecontrols.h"
#include "libs/compiler.h"
BOOLEAN MeleeShipDeath (STARSHIP *ship, COUNT which_player);
@@ -25,9 +28,54 @@ void MeleeGameOver (void);
BOOLEAN GetInitialMeleeStarShips (HSTARSHIP *result);
BOOLEAN GetNextMeleeStarShip (COUNT which_player, HSTARSHIP *result);
typedef struct getmelee_struct GETMELEE_STATE;
bool updateMeleeSelection (GETMELEE_STATE *gms, COUNT player, COUNT ship);
BOOLEAN selectShipHuman (HumanInputContext *context, GETMELEE_STATE *gms);
BOOLEAN selectShipComputer (ComputerInputContext *context,
GETMELEE_STATE *gms);
#ifdef NETPLAY
BOOLEAN selectShipNetwork (NetworkInputContext *context, GETMELEE_STATE *gms);
#endif /* NETPLAY */
#ifdef PICKMELE_INTERNAL
#include "flash.h"
#include "libs/timelib.h"
struct getmelee_struct {
BOOLEAN (*InputFunc) (struct getmelee_struct *pInputState);
COUNT MenuRepeatDelay;
BOOLEAN Initialized;
struct {
TimeCount timeIn;
HSTARSHIP hBattleShip;
// Chosen ship.
COUNT choice;
// Index of chosen ship, or (COUNT) ~0 for random choice.
COUNT row;
COUNT col;
COUNT ships_left;
// Number of ships still available.
COUNT randomIndex;
// Pre-generated random number.
BOOLEAN selecting;
// Is this player selecting a ship?
BOOLEAN done;
// Has a selection been made for this player?
FlashContext *flashContext;
// Context for controlling the flash rectangle.
#ifdef NETPLAY
BOOLEAN remoteSelected;
#endif
} player[NUM_PLAYERS];
};
bool setShipSelected(GETMELEE_STATE *gms, COUNT playerI, COUNT choice,
bool reportNetwork);
#endif /* PICKMELE_INTERNAL */
#endif /* _PICKMELE_H */
+7 -4
View File
@@ -21,6 +21,11 @@
#include "libs/compiler.h"
#include "units.h"
#include "displist.h"
typedef struct STARSHIP STARSHIP;
typedef HLINK HSTARSHIP;
#include "element.h"
#include "libs/sndlib.h"
#include "libs/reslib.h"
@@ -184,9 +189,7 @@ typedef struct
} SHIP_BASE;
typedef HLINK HSTARSHIP;
typedef struct
struct STARSHIP
{
SHIP_BASE_COMMON;
@@ -221,7 +224,7 @@ typedef struct
HELEMENT hShip;
COUNT ShipFacing;
} STARSHIP;
};
static inline STARSHIP *
LockStarShip (const QUEUE *pq, HSTARSHIP h)
-1
View File
@@ -420,7 +420,6 @@ StartGame (void)
PlayerControl[0] = HUMAN_CONTROL | STANDARD_RATING;
PlayerControl[1] = COMPUTER_CONTROL | AWESOME_RATING;
SetPlayerInput ();
return (TRUE);
}
+43 -27
View File
@@ -73,12 +73,6 @@ uio_DirHandle *rootDir;
static void
InitPlayerInput (void)
{
HumanInput[0] = combat_summary;
HumanInput[1] = combat_summary;
ComputerInput = computer_intelligence;
#ifdef NETPLAY
NetworkInput = networkBattleInput;
#endif
}
void
@@ -229,34 +223,56 @@ InitGameKernel (void)
}
void
SetPlayerInput (void)
SetPlayerInput (COUNT playerI)
{
COUNT which_player;
assert (PlayerInput[playerI] == NULL);
for (which_player = 0; which_player < NUM_PLAYERS; ++which_player)
{
if (PlayerControl[which_player] & COMPUTER_CONTROL)
PlayerInput[which_player] = ComputerInput;
else if (LOBYTE (GLOBAL (CurrentActivity)) != SUPER_MELEE)
{
// Full game.
if (which_player == 0)
PlayerInput[which_player] = HumanInput[0];
else
{
PlayerInput[which_player] = ComputerInput;
PlayerControl[which_player] = COMPUTER_CONTROL | AWESOME_RATING;
}
}
switch (PlayerControl[playerI] & CONTROL_MASK) {
case HUMAN_CONTROL:
PlayerInput[playerI] =
(InputContext *) HumanInputContext_new (playerI);
break;
case COMPUTER_CONTROL:
PlayerInput[playerI] =
(InputContext *) ComputerInputContext_new (playerI);
break;
#ifdef NETPLAY
else if (PlayerControl[which_player] & NETWORK_CONTROL)
PlayerInput[which_player] = NetworkInput;
case NETWORK_CONTROL:
PlayerInput[playerI] =
(InputContext *) NetworkInputContext_new (playerI);
break;
#endif
else
PlayerInput[which_player] = HumanInput[which_player];
default:
fprintf (stderr, "Invalid control method in SetPlayerInput().\n");
explode (); /* Does not return */
}
}
void
SetPlayerInputAll (void)
{
COUNT playerI;
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
SetPlayerInput (playerI);
}
void
ClearPlayerInput (COUNT playerI)
{
assert (PlayerInput[playerI] != NULL);
PlayerInput[playerI]->handlers->deleteContext (PlayerInput[playerI]);
PlayerInput[playerI] = NULL;
}
void
ClearPlayerInputAll (void)
{
COUNT playerI;
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
ClearPlayerInput (playerI);
}
int
initIO (void)
{
+9 -6
View File
@@ -57,14 +57,17 @@ extern ACTIVITY LastActivity;
extern BYTE PlayerControl[];
extern SIZE cur_player;
extern BOOLEAN InitContexts (void);
extern void UninitPlayerInput (void);
extern BOOLEAN InitGameKernel (void);
BOOLEAN InitContexts (void);
void UninitPlayerInput (void);
BOOLEAN InitGameKernel (void);
extern int initIO (void);
extern void uninitIO (void);
int initIO (void);
void uninitIO (void);
extern void SetPlayerInput (void);
void SetPlayerInput (COUNT playerI);
void SetPlayerInputAll (void);
void ClearPlayerInput (COUNT playerI);
void ClearPlayerInputAll (void);
#endif /* _SETUP_H */
+2
View File
@@ -150,6 +150,7 @@ while (--ac > 0)
// OpenJournal ();
while (StartGame ())
{
SetPlayerInputAll ();
InitSIS ();
InitGameClock ();
@@ -248,6 +249,7 @@ while (--ac > 0)
StopSound ();
UninitGameClock ();
UninitSIS ();
ClearPlayerInputAll ();
}
// CloseJournal ();
+27 -3
View File
@@ -16,6 +16,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "battlecontrols.h"
#include "build.h"
#include "collide.h"
#include "globdata.h"
@@ -119,7 +120,7 @@ readyToEndCallback (NetConnection *conn, void *arg)
* 5. The battle ends.
*/
static bool
readyForBattleEndPlayer (NetConnection *conn, void *arg)
readyForBattleEndPlayer (NetConnection *conn)
{
BattleStateData *battleStateData;
battleStateData = (BattleStateData *) NetConnection_getStateData(conn);
@@ -176,11 +177,30 @@ readyForBattleEndPlayer (NetConnection *conn, void *arg)
// We are ready and wait for the other party to become ready too.
negotiateReady (conn, true, NetState_interBattle);
(void) arg;
return true;
}
#endif
bool
battleEndReadyHuman (HumanInputContext *context)
{
(void) context;
return true;
}
bool
battleEndReadyComputer (ComputerInputContext *context)
{
(void) context;
return true;
}
bool
battleEndReadyNetwork (NetworkInputContext *context)
{
return readyForBattleEndPlayer (netConnections[context->playerNr]);
}
// Returns true iff this side is ready to end the battle.
static inline bool
readyForBattleEnd (COUNT side)
@@ -196,6 +216,8 @@ readyForBattleEnd (COUNT side)
return !PLRPlaying ((MUSIC_REF)~0);
#endif /* !DEMO_MODE */
#else /* defined (NETPLAY) */
int playerI;
if (PLRPlaying ((MUSIC_REF)~0))
return false;
@@ -213,7 +235,9 @@ readyForBattleEnd (COUNT side)
return false;
}
if (!forAllConnectedPlayers (readyForBattleEndPlayer, NULL))
for (playerI = 0; playerI < NUM_PLAYERS; playerI++)
if (!PlayerInput[playerI]->handlers->battleEndReady (
PlayerInput[playerI]))
return false;
currentDeadSide = (COUNT)~0;
+28
View File
@@ -0,0 +1,28 @@
//Copyright Paul Reiche, Fred Ford. 1992-2002
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef _TACTRANS_H
#define _TACTRANS_H
bool battleEndReadyHuman (COUNT side);
bool battleEndReadyComputer (COUNT side);
bool battleEndReadyNetwork (COUNT side);
#endif /* _TACTRANS_H */
+2
View File
@@ -31,6 +31,8 @@
#include "libs/input/input_common.h"
#include "libs/tasklib.h"
#include "controls.h"
#include "element.h"
// For BATTLE_FRAME_RATE
#include "file.h"
#include "port.h"
#include "libs/memlib.h"