tRevamped fighting code; the protagonist is penalised (cops may intervene and attack, probability of successful flight is halved) - vaccinewars - be a doctor and try to vaccinate the world
(HTM) git clone git://src.adamsgaard.dk/vaccinewars
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
(DIR) commit 43ce87336da1f84fc60b983b800e7590003cd8f0
(DIR) parent 93331be9af913e2a14cdf0c878fef43c2cd549af
(HTM) Author: Ben Webb <ben@salilab.org>
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(-)
---
(DIR) 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
(DIR) 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);
}
(DIR) 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,
(DIR) diff --git a/src/message.c b/src/message.c
t@@ -1170,13 +1170,13 @@ void FormatFightMessage(Player *To,GString *text,Player *Attacker,
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 {
(DIR) 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 Damage,
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);*/
(DIR) 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);