tRevamped fighting code; the protagonist is penalised (cops may intervene and a… | |
git clone git://src.adamsgaard.dk/vaccinewars | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit 43ce87336da1f84fc60b983b800e7590003cd8f0 | |
parent 93331be9af913e2a14cdf0c878fef43c2cd549af | |
Author: Ben Webb <[email protected]> | |
Date: Thu, 5 Apr 2001 01:13:05 +0000 | |
Revamped fighting code; the protagonist is penalised (cops may intervene | |
and attack, probability of successful flight is halved) | |
Diffstat: | |
M TODO | 2 +- | |
M src/dopewars.c | 11 ++--------- | |
M src/dopewars.h | 12 +++++++----- | |
M src/message.c | 6 +++--- | |
M src/serverside.c | 159 +++++++++++++++++++++--------… | |
M src/serverside.h | 2 -- | |
6 files changed, 120 insertions(+), 72 deletions(-) | |
--- | |
diff --git a/TODO b/TODO | |
t@@ -1,4 +1,4 @@ | |
-- Tidy up display of high scores in GUI client | |
+DONE - Tidy up display of high scores in GUI client | |
- Revamp player-player fighting; use same system for fighting the cops and | |
for fighting other players (perhaps the cops can intervene in fights); | |
add SWAT teams, soldiers, etc. as dealers get more and more guns | |
diff --git a/src/dopewars.c b/src/dopewars.c | |
t@@ -545,7 +545,7 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First) { | |
NewPlayer->Bank=0; | |
NewPlayer->Bitches.Carried=8; | |
NewPlayer->CopIndex=0; | |
- NewPlayer->Health=MaxHealth(NewPlayer,NewPlayer->Bitches.Carried); | |
+ NewPlayer->Health=100; | |
NewPlayer->CoatSize=100; | |
NewPlayer->Flags=0; | |
NewPlayer->ReadBuf.Data=NewPlayer->WriteBuf.Data=NULL; | |
t@@ -554,6 +554,7 @@ GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First) { | |
InitAbilities(NewPlayer); | |
if (Server) NewPlayer->fd=fd; | |
NewPlayer->FightArray=NULL; | |
+ NewPlayer->Attacking=NULL; | |
return g_slist_append(First,(gpointer)NewPlayer); | |
} | |
t@@ -602,14 +603,6 @@ void CopyPlayer(Player *Dest,Player *Src) { | |
Dest->Flags=Src->Flags; | |
} | |
-int MaxHealth(Player *Play,int NumBitches) { | |
- if (IsCop(Play)) | |
- return (Cop[Play->CopIndex-1].Health+ | |
- NumBitches*Cop[Play->CopIndex-1].DeputyHealth); | |
- else | |
- return (80+NumBitches*20); | |
-} | |
- | |
gboolean IsCop(Player *Play) { | |
return (Play->CopIndex>0); | |
} | |
diff --git a/src/dopewars.h b/src/dopewars.h | |
t@@ -70,6 +70,8 @@ typedef long price_t; | |
typedef long long price_t; | |
#endif | |
+/* "Abilities" are protocol extensions, which are negotiated between the | |
+ client and server at connect-time. */ | |
#define A_PLAYERID 0 /* Use numeric IDs rather than player names | |
in network messages */ | |
#define A_DRUGVALUE 1 /* Server keeps track of purchase price of drugs … | |
t@@ -77,9 +79,9 @@ typedef long long price_t; | |
#define A_TSTRING 3 /* We understand the %Txx (tstring) notation */ | |
#define A_NUM 4 | |
typedef struct ABILITIES { | |
- gboolean Local[A_NUM]; | |
- gboolean Remote[A_NUM]; | |
- gboolean Shared[A_NUM]; | |
+ gboolean Local[A_NUM]; /* Abilities that we have */ | |
+ gboolean Remote[A_NUM]; /* Those that the other end of the connection has … | |
+ gboolean Shared[A_NUM]; /* Abilites shared by us and the remote host */ | |
} Abilities; | |
struct NAMES { | |
t@@ -292,7 +294,8 @@ struct PLAYER_T { | |
Player *OnBehalfOf; | |
ConnBuf ReadBuf,WriteBuf; | |
Abilities Abil; | |
- GPtrArray *FightArray; | |
+ GPtrArray *FightArray; /* If non-NULL, a list of players in a fight */ | |
+ Player *Attacking; /* The player that this player is attacking */ | |
gint CopIndex; /* if >0, then this player is a cop, described | |
by Cop[CopIndex-1] | |
if ==0, this is a normal player that has killed no cops | |
t@@ -347,7 +350,6 @@ int CountPlayers(GSList *First); | |
GSList *AddPlayer(int fd,Player *NewPlayer,GSList *First); | |
void UpdatePlayer(Player *Play); | |
void CopyPlayer(Player *Dest,Player *Src); | |
-int MaxHealth(Player *Play,int NumBitches); | |
void ClearInventory(Inventory *Guns,Inventory *Drugs); | |
int IsCarryingRandom(Player *Play,int amount); | |
void ChangeSpaceForInventory(Inventory *Guns,Inventory *Drugs, | |
diff --git a/src/message.c b/src/message.c | |
t@@ -1170,13 +1170,13 @@ void FormatFightMessage(Player *To,GString *text,Playe… | |
ArmPercent<80 ? _("heavily armed") : | |
_("armed to the teeth"); | |
if (DefendName[0]) { | |
- if (IsCop(Defender)) { | |
+ if (IsCop(Defender) && !AttackName[0]) { | |
if (Bitches==0) { | |
- dpg_string_sprintfa(text,_("%s, %s, is chasing you, man!"), | |
+ dpg_string_sprintfa(text,_("%s - %s - is chasing you, man!"), | |
DefendName,Armament); | |
} else { | |
dpg_string_sprintfa(text, | |
- _("%s and %d %tde, %s, are chasing you, man!"), | |
+ _("%s and %d %tde - %s - are chasing you, man!"), | |
DefendName,Bitches,BitchesName,Armament); | |
} | |
} else { | |
diff --git a/src/serverside.c b/src/serverside.c | |
t@@ -1187,6 +1187,10 @@ void CopsAttackPlayer(Player *Play) { | |
gint CopIndex,NumDeputy,GunIndex; | |
CopIndex=1-Play->CopIndex; | |
+ if (CopIndex<0) { | |
+ g_warning(_("Cops cannot attack other cops!")); | |
+ return; | |
+ } | |
if (CopIndex > NumCop) CopIndex=NumCop; | |
Cops=g_new(Player,1); | |
FirstServer=AddPlayer(0,Cops,FirstServer); | |
t@@ -1200,7 +1204,7 @@ void CopsAttackPlayer(Player *Play) { | |
GunIndex=Cop[CopIndex-1].GunIndex; | |
if (GunIndex>=NumGun) GunIndex=NumGun-1; | |
Cops->Guns[GunIndex].Carried=NumDeputy+1; | |
- Cops->Health=MaxHealth(Cops,NumDeputy); | |
+ Cops->Health=100; | |
Play->EventNum++; | |
AttackPlayer(Cops,Play); | |
t@@ -1217,41 +1221,37 @@ void AttackPlayer(Player *Play,Player *Attacked) { | |
if (Play->FightArray && Attacked->FightArray) { | |
if (Play->FightArray==Attacked->FightArray) { | |
- g_warning("Players are already in a fight!"); | |
+ g_warning(_("Players are already in a fight!")); | |
} else { | |
- g_warning("Players are already in separate fights!"); | |
+ g_warning(_("Players are already in separate fights!")); | |
} | |
return; | |
} | |
- if (Play->FightArray) { | |
- FightArray=Play->FightArray; | |
- AddPlayerToFight(Attacked,FightArray,Play,TRUE); | |
- } else if (Attacked->FightArray) { | |
- FightArray=Attacked->FightArray; | |
- AddPlayerToFight(Play,FightArray,Attacked,TRUE); | |
+ if (!Play->FightArray && !Attacked->FightArray) { | |
+ FightArray = g_ptr_array_new(); | |
} else { | |
- FightArray=g_ptr_array_new(); | |
- AddPlayerToFight(Attacked,FightArray,Play,TRUE); | |
- AddPlayerToFight(Play,FightArray,Attacked,FALSE); | |
+ FightArray = Play->FightArray ? Play->FightArray : Attacked->FightArray; | |
+ } | |
+ | |
+ if (!Play->FightArray) { | |
+ Play->ResyncNum=Play->EventNum; | |
+ g_ptr_array_add(FightArray,Play); | |
+ } | |
+ if (!Attacked->FightArray) { | |
+ Attacked->ResyncNum=Attacked->EventNum; | |
+ g_ptr_array_add(FightArray,Attacked); | |
} | |
+ Play->FightArray=Attacked->FightArray=FightArray; | |
+ Play->EventNum=Attacked->EventNum=E_FIGHT; | |
+ | |
+ Play->Attacking = Attacked; | |
+ | |
+ SendFightMessage(Attacked,Play,0,F_ARRIVED,FALSE,TRUE,NULL); | |
Fire(Play); | |
} | |
-void AddPlayerToFight(Player *NewPlay,GPtrArray *Fight,Player *Other, | |
- gboolean Inform) { | |
-/* Adds the player "NewPlay" to the fight "Fight", and informs any */ | |
-/* players already in the fight of the new player's arrival, if */ | |
-/* "Inform" is TRUE. "Other" is a player already in the fight. */ | |
- NewPlay->FightArray=Fight; | |
- NewPlay->ResyncNum=NewPlay->EventNum; | |
- NewPlay->EventNum=E_FIGHT; | |
- | |
- g_ptr_array_add(Fight,NewPlay); | |
- if (Inform) SendFightMessage(NewPlay,Other,0,F_ARRIVED,FALSE,TRUE,NULL); | |
-} | |
- | |
gboolean IsOpponent(Player *Play,Player *Other) { | |
/* Returns TRUE if player "Other" is not allied with player "Play" */ | |
return TRUE; | |
t@@ -1273,10 +1273,9 @@ void HandleDamage(Player *Defend,Player *Attack,int Dam… | |
AddInventory(Drugs,Defend->Drugs,NumDrug); | |
Defend->Health=0; | |
} else if (Defend->Bitches.Carried>0 && | |
- Defend->Health-Damage <= | |
- MaxHealth(Defend,Defend->Bitches.Carried-1)) { | |
+ Defend->Health<=Damage) { | |
LoseBitch(Defend,Guns,Drugs); | |
- Defend->Health=MaxHealth(Defend,Defend->Bitches.Carried); | |
+ Defend->Health=100; | |
*BitchesKilled=1; | |
} else { | |
Defend->Health-=Damage; | |
t@@ -1352,7 +1351,11 @@ void RunFromCombat(Player *Play) { | |
if (!Play || !Play->FightArray) return; | |
- EscapeProb=50; | |
+ EscapeProb=60; | |
+ | |
+/* Penalise players that are attacking others */ | |
+ if (Play->Attacking) EscapeProb/=2; | |
+ | |
RandNum=brandom(0,100); | |
if (RandNum<EscapeProb) { | |
t@@ -1366,7 +1369,7 @@ void RunFromCombat(Player *Play) { | |
WithdrawFromCombat(Play); | |
Play->EventNum=Play->ResyncNum; SendEvent(Play); | |
} else { | |
- SendFightMessage(Play,NULL,0,F_MSG,FALSE,FALSE,"You can't get away!"); | |
+ SendFightMessage(Play,NULL,0,F_MSG,FALSE,FALSE,_("You can't get away!")); | |
AllowNextShooter(Play); | |
DoReturnFire(Play); | |
} | |
t@@ -1400,10 +1403,56 @@ void CheckForKilledPlayers(Player *Play) { | |
g_ptr_array_free(KilledPlayers,FALSE); | |
} | |
+static void CheckCopsIntervene(Player *Play) { | |
+/* If "Play" is attacking someone, and no cops are currently present, */ | |
+/* then have the cops intervene (with a probability dependent on the */ | |
+/* current location's PolicePresence) */ | |
+ gint ArrayInd; | |
+ Player *Defend; | |
+ | |
+ if (!Play || !Play->FightArray) return; /* Sanity check */ | |
+ | |
+ if (!Play->Attacking) return; /* Cops don't attack "innocent victims" ;) */ | |
+ | |
+ if (brandom(0,100) > Location[(int)Play->IsAt].PolicePresence) { | |
+ return; /* The cops shouldn't _always_ attack (unless P.P. == 100) */ | |
+ } | |
+ | |
+ for (ArrayInd=0;Play->FightArray && ArrayInd<Play->FightArray->len; | |
+ ArrayInd++) { | |
+ Defend=(Player *)g_ptr_array_index(Play->FightArray,ArrayInd); | |
+ if (IsCop(Defend)) return; /* We don't want _more_ cops! */ | |
+ } | |
+ | |
+ /* OK - let 'em have it... */ | |
+ CopsAttackPlayer(Play); | |
+} | |
+ | |
+static Player *GetFireTarget(Player *Play) { | |
+/* Returns a suitable player (or cop) for "Play" to fire at. If "Play" */ | |
+/* is attacking a designated target already, return that, otherwise */ | |
+/* return the first valid opponent in the player's FightArray. */ | |
+ Player *Defend; | |
+ gint ArrayInd; | |
+ | |
+ if (Play->Attacking && g_slist_find(FirstServer,(gpointer)Play->Attacking))… | |
+ return Play->Attacking; | |
+ } else { | |
+ Play->Attacking=NULL; | |
+ for (ArrayInd=0;ArrayInd<Play->FightArray->len;ArrayInd++) { | |
+ Defend=(Player *)g_ptr_array_index(Play->FightArray,ArrayInd); | |
+ if (Defend && Defend!=Play && IsOpponent(Play,Defend)) { | |
+ return Defend; | |
+ } | |
+ } | |
+ } | |
+ return NULL; | |
+} | |
+ | |
void Fire(Player *Play) { | |
-/* Fires all weapons of player "Play" at all opponents, and resets */ | |
-/* the fight timeout (the reload time) */ | |
- int Damage,ArrayInd,i,j; | |
+/* Fires all weapons of player "Play" at an opponent, and resets */ | |
+/* the fight timeout (the reload time) */ | |
+ int Damage,i,j; | |
int AttackRating,DefendRating; | |
int BitchesKilled; | |
gboolean Loot; | |
t@@ -1416,29 +1465,28 @@ void Fire(Player *Play) { | |
AllowNextShooter(Play); | |
if (FightTimeout) SetFightTimeout(Play); | |
- for (ArrayInd=0;ArrayInd<Play->FightArray->len;ArrayInd++) { | |
- Defend=(Player *)g_ptr_array_index(Play->FightArray,ArrayInd); | |
- | |
- if (Defend && Defend!=Play && IsOpponent(Play,Defend)) { | |
- Damage=0; BitchesKilled=0; Loot=FALSE; | |
- if (TotalGunsCarried(Play)>0) { | |
- GetFightRatings(Play,Defend,&AttackRating,&DefendRating); | |
- if (brandom(0,AttackRating)>brandom(0,DefendRating)) { | |
- FightPoint=F_HIT; | |
- for (i=0;i<NumGun;i++) for (j=0;j<Play->Guns[i].Carried;j++) { | |
- Damage+=brandom(0,Gun[i].Damage); | |
- } | |
- if (Damage==0) Damage=1; | |
- HandleDamage(Defend,Play,Damage,&BitchesKilled,&Loot); | |
- } else FightPoint=F_MISS; | |
- } else FightPoint=F_STAND; | |
- SendFightMessage(Play,Defend,BitchesKilled,FightPoint,Loot,TRUE,NULL); | |
- } | |
+ Defend = GetFireTarget(Play); | |
+ if (Defend) { | |
+ Damage=0; BitchesKilled=0; Loot=FALSE; | |
+ if (TotalGunsCarried(Play)>0) { | |
+ GetFightRatings(Play,Defend,&AttackRating,&DefendRating); | |
+ if (brandom(0,AttackRating)>brandom(0,DefendRating)) { | |
+ FightPoint=F_HIT; | |
+ for (i=0;i<NumGun;i++) for (j=0;j<Play->Guns[i].Carried;j++) { | |
+ Damage+=brandom(0,Gun[i].Damage); | |
+ } | |
+ if (Damage==0) Damage=1; | |
+ HandleDamage(Defend,Play,Damage,&BitchesKilled,&Loot); | |
+ } else FightPoint=F_MISS; | |
+ } else FightPoint=F_STAND; | |
+ SendFightMessage(Play,Defend,BitchesKilled,FightPoint,Loot,TRUE,NULL); | |
} | |
CheckForKilledPlayers(Play); | |
/* Careful, as we might have killed Player "Play" */ | |
if (g_slist_find(FirstServer,(gpointer)Play)) DoReturnFire(Play); | |
+ | |
+ if (g_slist_find(FirstServer,(gpointer)Play)) CheckCopsIntervene(Play); | |
} | |
gboolean CanPlayerFire(Player *Play) { | |
t@@ -1501,6 +1549,7 @@ void WithdrawFromCombat(Player *Play) { | |
int i,j; | |
gboolean FightDone; | |
Player *Attack,*Defend; | |
+ GSList *list; | |
if (!Play->FightArray) return; | |
t@@ -1516,6 +1565,11 @@ void WithdrawFromCombat(Player *Play) { | |
if (!FightDone) break; | |
} | |
+ for (list=FirstServer;list;list=g_slist_next(list)) { | |
+ Attack=(Player *)list->data; | |
+ if (Attack->Attacking==Play) Attack->Attacking=NULL; | |
+ } | |
+ | |
SendFightLeave(Play,FightDone); | |
g_ptr_array_remove(Play->FightArray,(gpointer)Play); | |
t@@ -1535,6 +1589,7 @@ void WithdrawFromCombat(Player *Play) { | |
g_ptr_array_free(Play->FightArray,TRUE); | |
} | |
Play->FightArray=NULL; | |
+ Play->Attacking=NULL; | |
} | |
int RandomOffer(Player *To) { | |
t@@ -1818,7 +1873,7 @@ void HandleAnswer(Player *From,Player *To,char *answer) { | |
case E_DOCTOR: | |
if (From->Cash >= From->DocPrice) { | |
From->Cash -= From->DocPrice; | |
- From->Health=MaxHealth(From,From->Bitches.Carried); | |
+ From->Health=100; | |
SendPlayerData(From); | |
} | |
/* FinishFightWithHardass(From,NULL);*/ | |
diff --git a/src/serverside.h b/src/serverside.h | |
t@@ -69,8 +69,6 @@ gboolean CheckHighScoreFile(); | |
int HighScoreRead(struct HISCORE *MultiScore,struct HISCORE *AntiqueScore); | |
void CopsAttackPlayer(Player *Play); | |
void AttackPlayer(Player *Play,Player *Attacked); | |
-void AddPlayerToFight(Player *NewPlay,GPtrArray *Fight,Player *Other, | |
- gboolean Inform); | |
gboolean IsOpponent(Player *Play,Player *Other); | |
void Fire(Player *Play); | |
void WithdrawFromCombat(Player *Play); |