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) 2014, 2016-2017, 2019 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 #include "objective.h"
50
51 #include "json_utils.h"
52 #include "utils.h"
53
54
ObjectiveTypeStr(const ObjectiveType t)55 const char *ObjectiveTypeStr(const ObjectiveType t)
56 {
57 switch (t)
58 {
59 T2S(OBJECTIVE_KILL, "Kill");
60 T2S(OBJECTIVE_COLLECT, "Collect");
61 T2S(OBJECTIVE_DESTROY, "Destroy");
62 T2S(OBJECTIVE_RESCUE, "Rescue");
63 T2S(OBJECTIVE_INVESTIGATE, "Explore");
64 default:
65 return "";
66 }
67 }
StrObjectiveType(const char * s)68 ObjectiveType StrObjectiveType(const char *s)
69 {
70 S2T(OBJECTIVE_KILL, "Kill");
71 S2T(OBJECTIVE_COLLECT, "Collect");
72 S2T(OBJECTIVE_DESTROY, "Destroy");
73 S2T(OBJECTIVE_RESCUE, "Rescue");
74 S2T(OBJECTIVE_INVESTIGATE, "Explore");
75 CASSERT(false, "unknown objective name");
76 return OBJECTIVE_KILL;
77 }
ObjectiveTypeColor(const ObjectiveType t)78 color_t ObjectiveTypeColor(const ObjectiveType t)
79 {
80 switch (t)
81 {
82 case OBJECTIVE_KILL: // fallthrough
83 case OBJECTIVE_DESTROY:
84 return colorRed;
85 case OBJECTIVE_COLLECT: // fallthrough
86 case OBJECTIVE_RESCUE:
87 return colorGreen;
88 case OBJECTIVE_INVESTIGATE:
89 return colorCyan;
90 default:
91 CASSERT(false, "unknown objective type");
92 // Shouldn't get here but use a different colour in case
93 return colorYellow;
94 }
95 }
96
ObjectiveLoadJSON(Objective * o,json_t * node,const int version)97 void ObjectiveLoadJSON(Objective *o, json_t *node, const int version)
98 {
99 memset(o, 0, sizeof *o);
100 o->Description = GetString(node, "Description");
101 JSON_UTILS_LOAD_ENUM(o->Type, node, "Type", StrObjectiveType);
102 if (version < 8)
103 {
104 // Index numbers used for all objective classes; convert them
105 // to their class handles
106 LoadInt(&o->u.Index, node, "Index");
107 switch (o->Type)
108 {
109 case OBJECTIVE_COLLECT:
110 o->u.Pickup = IntPickupClass(o->u.Index);
111 break;
112 case OBJECTIVE_DESTROY:
113 o->u.MapObject = IntMapObject(o->u.Index);
114 break;
115 default:
116 // do nothing
117 break;
118 }
119 }
120 else
121 {
122 char *tmp;
123 switch (o->Type)
124 {
125 case OBJECTIVE_COLLECT:
126 tmp = GetString(node, "Pickup");
127 o->u.Pickup = StrPickupClass(tmp);
128 CFREE(tmp);
129 break;
130 case OBJECTIVE_DESTROY:
131 tmp = GetString(node, "MapObject");
132 o->u.MapObject = StrMapObject(tmp);
133 CFREE(tmp);
134 break;
135 default:
136 LoadInt(&o->u.Index, node, "Index");
137 break;
138 }
139 }
140 LoadInt(&o->Count, node, "Count");
141 LoadInt(&o->Required, node, "Required");
142 LoadInt(&o->Flags, node, "Flags");
143 if (version < 14)
144 {
145 // Classic objective flags: rescue always in locked rooms, kill always
146 // anywhere
147 if (o->Type == OBJECTIVE_RESCUE)
148 {
149 o->Flags |= OBJECTIVE_HIACCESS;
150 o->Flags &= ~OBJECTIVE_NOACCESS;
151 }
152 else if (o->Type == OBJECTIVE_KILL)
153 {
154 o->Flags &= ~(OBJECTIVE_HIACCESS | OBJECTIVE_NOACCESS);
155 }
156 }
157 }
ObjectiveSetup(Objective * o)158 void ObjectiveSetup(Objective *o)
159 {
160 // Set objective colours based on type
161 o->color = ObjectiveTypeColor(o->Type);
162 o->placed = 0;
163 o->done = 0;
164 }
ObjectiveCopy(Objective * dst,const Objective * src)165 void ObjectiveCopy(Objective *dst, const Objective *src)
166 {
167 memcpy(dst, src, sizeof *dst);
168 if (src->Description)
169 {
170 CSTRDUP(dst->Description, src->Description);
171 }
172 }
ObjectiveTerminate(Objective * o)173 void ObjectiveTerminate(Objective *o)
174 {
175 CFREE(o->Description);
176 }
177
ObjectiveIsRequired(const Objective * o)178 bool ObjectiveIsRequired(const Objective *o)
179 {
180 return o->Required > 0;
181 }
ObjectiveIsComplete(const Objective * o)182 bool ObjectiveIsComplete(const Objective *o)
183 {
184 return o->done >= o->Required;
185 }
ObjectiveIsPerfect(const Objective * o)186 bool ObjectiveIsPerfect(const Objective *o)
187 {
188 // Don't count objectives that are fully required anyway
189 return o->done == o->Count && o->done > o->Required;
190 }
191
ObjectiveGetPlacementAccessFlags(const Objective * o)192 PlacementAccessFlags ObjectiveGetPlacementAccessFlags(const Objective *o)
193 {
194 if (o->Flags & OBJECTIVE_HIACCESS)
195 {
196 return PLACEMENT_ACCESS_LOCKED;
197 }
198 if (o->Flags & OBJECTIVE_NOACCESS)
199 {
200 return PLACEMENT_ACCESS_NOT_LOCKED;
201 }
202 return PLACEMENT_ACCESS_ANY;
203 }
204