1 /*
2 	C-Dogs SDL
3 	A port of the legendary (and fun) action/arcade cdogs.
4 	Copyright (C) 1995 Ronny Wester
5 	Copyright (C) 2003 Jeremy Chin
6 	Copyright (C) 2003-2007 Lucas Martin-King
7 
8 	This program is free software; you can redistribute it and/or modify
9 	it under the terms of the GNU General Public License as published by
10 	the Free Software Foundation; either version 2 of the License, or
11 	(at your option) any later version.
12 
13 	This program is distributed in the hope that it will be useful,
14 	but WITHOUT ANY WARRANTY; without even the implied warranty of
15 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 	GNU General Public License for more details.
17 
18 	You should have received a copy of the GNU General Public License
19 	along with this program; if not, write to the Free Software
20 	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 
22 	This file incorporates work covered by the following copyright and
23 	permission notice:
24 
25 	Copyright (c) 2013-2021 Cong Xu
26 	All rights reserved.
27 
28 	Redistribution and use in source and binary forms, with or without
29 	modification, are permitted provided that the following conditions are met:
30 
31 	Redistributions of source code must retain the above copyright notice, this
32 	list of conditions and the following disclaimer.
33 	Redistributions in binary form must reproduce the above copyright notice,
34 	this list of conditions and the following disclaimer in the documentation
35 	and/or other materials provided with the distribution.
36 
37 	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
38 	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 	ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
41 	LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
42 	CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
43 	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
44 	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
45 	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
47 	POSSIBILITY OF SUCH DAMAGE.
48 */
49 #pragma once
50 
51 #include "ai_context.h"
52 #include "animation.h"
53 #include "emitter.h"
54 #include "game_mode.h"
55 #include "grafx.h"
56 #include "mathc/mathc.h"
57 #include "player.h"
58 #include "thing.h"
59 #include "weapon.h"
60 
61 #define ACTOR_W 14
62 #define ACTOR_H 10
63 
64 #define FLAGS_HURTALWAYS (1 << 2)
65 
66 // Computer characters only
67 #define FLAGS_DETOURING (1 << 5)
68 #define FLAGS_TRYRIGHT (1 << 6)
69 #define FLAGS_SLEEPING (1 << 7)
70 #define FLAGS_VISIBLE (1 << 8)
71 #define FLAGS_ASBESTOS (1 << 9)	   // Immune to fire
72 #define FLAGS_IMMUNITY (1 << 10)   // Immune to poison
73 #define FLAGS_SEETHROUGH (1 << 11) // Almost transparent
74 #define FLAGS_DEAF (1 << 12)
75 #define FLAGS_WAKING (1 << 13)
76 
77 // Special flags
78 #define FLAGS_RUNS_AWAY (1 << 16) // Move directly away from player
79 #define FLAGS_GOOD_GUY (1 << 17)  // Shots cannot hurt player
80 #define FLAGS_PRISONER (1 << 18)  // Won't move until touched by player
81 #define FLAGS_INVULNERABLE (1 << 19)
82 #define FLAGS_FOLLOWER (1 << 20) // Follows player
83 #define FLAGS_PENALTY (1 << 21)	 // Big score penalty if shot
84 #define FLAGS_VICTIM (1 << 22)	 // Can be shot by everyone
85 #define FLAGS_SNEAKY (1 << 23)	 // Always shoot back when player shoots
86 #define FLAGS_SLEEPALWAYS (1 << 24)
87 #define FLAGS_AWAKEALWAYS (1 << 25)
88 #define FLAGS_RESCUED (1 << 26) // Run towards exit
89 
90 typedef enum
91 {
92 	ACTORACTION_MOVING,
93 	ACTORACTION_EXITING
94 } ActorAction;
95 
96 typedef struct Actor
97 {
98 	struct vec2 Pos;
99 	// Vector that the player is attempting to move in, based on input
100 	struct vec2 MoveVel;
101 	direction_e direction;
102 	// Rotation used to draw the actor, which will lag behind the actual
103 	// rotation in order to show smooth rotation
104 	float DrawRadians;
105 	Animation anim;
106 	int stateCounter;
107 	int lastCmd;
108 	// Whether the player ran into something whilst trying to move
109 	// In this situation, we interrupt dead reckoning and resend the position
110 	bool hasCollided;
111 	// Whether the last special command was performed with a direction
112 	// This differentiates between a special command and weapon switch
113 	bool specialCmdDir;
114 	// If the actor wants to pick up everything, even those that need to be
115 	// manually picked up using special input
116 	bool PickupAll;
117 	// Flag to specify whether this actor is over a special pickup,
118 	// such as weapons which will replace the current weapon.
119 	// If the player presses switch when in this state, instead of switching
120 	// weapons, pick up.
121 	bool CanPickupSpecial;
122 
123 	// -1 if human character (get from player data), otherwise index into
124 	// CharacterStore OtherChars
125 	int charId;
126 	int PlayerUID; // -1 unless a human player
127 	int uid;	   // unique ID across all actors
128 	int pilotUID;  // the actor that controls this
129 				  // (same as uid for normal actors)
130 	int vehicleUID; // -1 unless piloting a vehicle
131 	Weapon guns[MAX_WEAPONS];
132 	CArray ammo; // of int
133 	int gunIndex;
134 	// TODO: multiple grenade slots?
135 	int grenadeIndex;
136 
137 	int health;
138 	// A counter for player death
139 	// If 0, player is alive
140 	// If >0 but less than deathPics, player is "dying" and this variable
141 	// is used as the frame in the death animation
142 	int dead;
143 	int flamed;
144 	int poisoned;
145 	int petrified;
146 	int confused;
147 	int flags;
148 
149 	int turns;
150 
151 	int slideLock;
152 	// For damage text
153 	int accumulatedDamage;
154 	// Facial expression when melee or taking damage
155 	int grimaceCounter;
156 
157 	// What to say (text label appears above actor) and how long to say it
158 	char Chatter[256];
159 	int ChatterCounter;
160 
161 	Emitter barrelSmoke;
162 	Emitter healEffect;
163 
164 	// Gore emitters
165 	Emitter blood1;
166 	Emitter blood2;
167 	Emitter blood3;
168 	int bleedCounter;
169 
170 	// Signals to other AIs what this actor is doing
171 	ActorAction action;
172 	AIContext *aiContext;
173 	Thing thing;
174 	bool isInUse;
175 } TActor;
176 
177 // Store all actors in-line in an array
178 // Destroying actors does not modify the array, only switches
179 // a boolean flag isInUse to denote whether this instance is
180 // in use.
181 // Actors should be identified by index
182 // There is a small chance of invalidating pointers if
183 // actors are added and the array must be resized.
184 // Therefore do not hold actor pointers and reuse.
185 extern CArray gActors; // of TActor
186 
187 void ActorSetState(TActor *actor, const ActorAnimation state);
188 void UpdateActorState(TActor *actor, int ticks);
189 bool TryMoveActor(TActor *actor, struct vec2 pos);
190 void ActorMove(const NActorMove am);
191 void CommandActor(TActor *actor, int cmd, int ticks);
192 void SlideActor(TActor *actor, int cmd);
193 void UpdateAllActors(const int ticks);
194 void ActorsPilotVehicles(void);
195 void ActorHeal(TActor *actor, int health);
196 void InjureActor(TActor *actor, int injury);
197 
198 void ActorAddAmmo(TActor *actor, const int ammoId, const int amount);
199 // Whether the actor has a gun that uses this ammo
200 bool ActorUsesAmmo(const TActor *actor, const int ammoId);
201 void ActorReplaceGun(const NActorReplaceGun rg);
202 void ActorSetAIState(TActor *actor, const AIState s);
203 void ActorPilot(const NActorPilot ap);
204 
205 void ActorsInit(void);
206 void ActorsTerminate(void);
207 int ActorsGetNextUID(void);
208 int ActorsGetFreeIndex(void);
209 TActor *ActorAdd(NActorAdd aa);
210 void ActorDestroy(TActor *a);
211 
212 TActor *ActorGetByUID(const int uid);
213 const Character *ActorGetCharacter(const TActor *a);
214 #define ACTOR_GET_GUN(a) (&(a)->guns[(a)->gunIndex])
215 #define ACTOR_GET_GRENADE(a) (&(a)->guns[(a)->grenadeIndex + MAX_GUNS])
216 #define ACTOR_GET_WEAPON(a)                                                   \
217 	(ACTOR_GET_GUN(a)->Gun != NULL ? ACTOR_GET_GUN(a) : ACTOR_GET_GRENADE(a))
218 struct vec2 ActorGetAverageWeaponMuzzleOffset(const TActor *a);
219 struct vec2 ActorGetMuzzleOffset(
220 	const TActor *a, const Weapon *w, const int barrel);
221 // Returns -1 if gun does not use ammo
222 int ActorWeaponGetAmmo(
223 	const TActor *a, const WeaponClass *wc, const int barrel);
224 // Returns -1 if no barrels can fire
225 int ActorGetCanFireBarrel(const TActor *a, const Weapon *w);
226 bool ActorTrySwitchWeapon(const TActor *a, const bool allGuns);
227 // Returns -1 if actor doesn't have gun
228 int ActorFindGun(const TActor *a, const WeaponClass *wc);
229 int ActorGetNumWeapons(const TActor *a);
230 int ActorGetNumGuns(const TActor *a);
231 int ActorGetNumGrenades(const TActor *a);
232 void ActorSwitchGun(const NActorSwitchGun sg);
233 bool ActorIsImmune(const TActor *actor, const special_damage_e damage);
234 bool ActorTakesDamage(const TActor *actor, const special_damage_e damage);
235 void ActorHit(const NThingDamage d);
236 bool ActorIsInvulnerable(
237 	const TActor *a, const int flags, const int playerUID, const GameMode mode,
238 	const special_damage_e special);
239 
240 int ActorGetHealthPercent(const TActor *a);
241 bool ActorIsLowHealth(const TActor *a);
242 bool ActorIsGrimacing(const TActor *a);
243 
244 bool ActorIsLocalPlayer(const int uid);
245