1 /*
2 This file is part of "Avanor, the Land of Mystery" roguelike game
3 Home page: http://www.avanor.com/
4 Copyright (C) 2000-2003 Vadim Gaidukevich
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20 
21 #include "skill.h"
22 #include "creature.h"
23 #include "other_misc.h"
24 
25 REGISTER_CLASS(XSkill);
26 
27 SKILL_DB skill_db[] = {
28 {"Archery",         1},
29 {"Find Weakness",   1},
30 {"Healing",         2},
31 {"Concentration",   3},
32 {"Dodge",           1},
33 {"Trading",         1},
34 {"Stealing",        1},
35 {"Literacy",        1},
36 {"Detect trap",     1},
37 {"Disarm trap",     1},
38 {"Cooking",         1},
39 {"Mining",          5},
40 {"Herbalism",       1},
41 {"Religion",        1},
42 {"Backstabbing",    1},
43 {"First aid",		2},
44 {"Tactics",			1},
45 {"Alchemy",			1},
46 {"Woodcraft",		1},
47 {"Create trap",		1},
48 {"Necromancy",		1},
49 {"Athletics",		1},
50 };
51 
52 char * skill_level_name[16] = {
53 MSG_LIGHTGRAY       "NONE",
54 MSG_LIGHTGREEN      "Basic",
55 MSG_LIGHTGREEN      "Basic",
56 MSG_LIGHTGREEN      "Basic",
57 MSG_GREEN           "Skilled",
58 MSG_GREEN           "Skilled",
59 MSG_GREEN           "Skilled",
60 MSG_GREEN           "Skilled",
61 MSG_YELLOW          "Expert",
62 MSG_YELLOW          "Expert",
63 MSG_YELLOW          "Expert",
64 MSG_YELLOW          "Expert",
65 MSG_LIGHTRED        "Master",
66 MSG_LIGHTRED        "Master",
67 MSG_LIGHTRED        "Master",
68 MSG_DARKGRAY        "Grand Master"
69 };
70 
71 
XSkill(SKILL_TYPE _skt,int _level)72 XSkill::XSkill(SKILL_TYPE _skt, int _level)
73 {
74 	skt = _skt;
75 	level = _level;
76 	im = IM_OTHER;
77 	if (_level < 4)
78 	{
79 		used_time = skill_db[skt].use_per_level * (4 * 4 - 1) * 2;
80 	} else
81 	{
82 		used_time = skill_db[skt].use_per_level * (level * level - 1) * 2;
83 	}
84 }
85 
GetName()86 char * XSkill::GetName()
87 {
88 	return skill_db[skt].name;
89 }
90 
GetSkillLevel()91 char * XSkill::GetSkillLevel()
92 {
93 	assert(level <= SKILL_MAX_LEVEL);
94 	return skill_level_name[level];
95 }
96 
GetMaxLevel()97 int XSkill::GetMaxLevel()
98 {
99 	int xlevel = (int)(sqrt(used_time / (2 * skill_db[skt].use_per_level) + 1));
100 	return xlevel < 15 ? xlevel : 15;
101 }
102 
IncLevel()103 int XSkill::IncLevel()
104 {
105 	if (level < GetMaxLevel())
106 	{
107 		level++;
108 		return 1;
109 	} else
110 	{
111 		return 0;
112 	}
113 }
114 
GetMastery()115 SKILL_MASTERY XSkill::GetMastery()
116 {
117 	switch (level)
118 	{
119 		case 1 :
120 		case 2 :
121 		case 3 : return SM_BASIC; break;
122 		case 4 :
123 		case 5 :
124 		case 6 :
125 		case 7 : return SM_SKILLED; break;
126 		case 8 :
127 		case 9 :
128 		case 10:
129 		case 11: return SM_EXPERT; break;
130 		case 12:
131 		case 13:
132 		case 14: return SM_MASTER; break;
133 		case 15: return SM_GRANDMASTER; break;
134 	}
135 	return SM_BASIC;
136 }
137 
Use(XCreature * user)138 int XSkill::Use(XCreature * user)
139 {
140 	switch (skt)
141 	{
142 		case SKT_STEALING :			return UseSteal(user);
143 		case SKT_DISARMTRAP :		return UseDisarm(user);
144 		case SKT_CREATETRAP:		return UseCreate(user);
145 
146 	};
147 	return 1;
148 }
149 
isUseable()150 int XSkill::isUseable()
151 {
152 	if (skt == SKT_STEALING || skt == SKT_DISARMTRAP || skt == SKT_CREATETRAP)
153 		return 1;
154 	else
155 		return 0;
156 }
157 
158 
UseSkill(int n)159 void XSkill::UseSkill(int n)
160 {
161 	used_time += n;
162 }
163 
Store(XFile * f)164 void XSkill::Store(XFile * f)
165 {
166 	XObject::Store(f);
167 
168 	f->Write(&level, sizeof(int));
169 	f->Write(&skt, sizeof(SKILL_TYPE));
170 	f->Write(&used_time, sizeof(int));
171 }
172 
Restore(XFile * f)173 void XSkill::Restore(XFile * f)
174 {
175 	XObject::Restore(f);
176 
177 	f->Read(&level, sizeof(int));
178 	f->Read(&skt, sizeof(SKILL_TYPE));
179 	f->Read(&used_time, sizeof(int));
180 }
181 
182 
Compare(XObject * o)183 int XSkill::Compare(XObject * o)
184 {
185 	return strcmp(GetName(), ((XSkill *)o)->GetName());
186 }
187 
188 
UseSteal(XCreature * user)189 int XSkill::UseSteal(XCreature * user)
190 {
191 	XPoint pt;
192 	XItem * object;
193 	if (user->GetTarget(TR_STEAL_ITEM, &pt, 0, (XObject **)&object))
194 	{
195 		if (pt.x == 0 && pt.y == 0)
196 		{
197 			msgwin.Add("Stealing from yourself? You are successful!");
198 			user->contain.Add(object);
199 		} else
200 		{
201 			XCreature * cr = user->l->map->GetMonster(user->x + pt.x, user->y + pt.y);
202 			int flag = 0;
203 			if (cr == NULL)
204 			{
205 				XAnyPlace * pl = user->l->map->GetPlace(user->x + pt.x, user->y + pt.y);
206 				if (pl)
207 				{
208 					cr = pl->GetOwner().get();
209 					flag = 1;
210 				}
211 			}
212 			assert(cr);
213 			double perception = 1 + cr->s->Get(S_PER);
214 			double stealing = 1 + user->sk->GetLevel(SKT_STEALING);
215 			int p = (int)((stealing * 300) / perception);
216 			if (vRand() % 100 < p || !user->isVisible())
217 			{
218 				if (user->isVisible())
219 				{
220 					char buf[256];
221 					XItem * it = (XItem *)object;
222 					it->toString(buf);
223 					char buf2[256];
224 					sprintf(buf2, "You steal %s.", buf);
225 					msgwin.Add(buf2);
226 				}
227 				cr->UnCarryItem((XItem *)object);
228 				user->CarryItem((XItem *)object);
229 				user->contain.Add(object);
230 				UseSkill(6);
231 			} else
232 			{
233 				if (user->isVisible())
234 				{
235 					msgwin.Add(cr->name);
236 					msgwin.Add("notices your efforts and becomes angry.");
237 				}
238 				cr->xai->onSteal(user);
239 				if (flag)
240 				{
241 					(user->l->map->GetItemList(user->x + pt.x, user->y + pt.y))->Add(object);
242 				} else
243 				{
244 					cr->contain.Add(object);
245 				}
246 			}
247 		}
248 	}
249 	return 1;
250 }
251 
UseDisarm(XCreature * user)252 int XSkill::UseDisarm(XCreature * user)
253 {
254 	XMapObject * obj = user->l->map->GetSpecial(user->x, user->y);
255 	if (obj && obj->im & IM_TRAP)
256 	{
257 		if (((XTrap *)obj)->Disarm(user))
258 			UseSkill(1);
259 	} else
260 		msgwin.Add("There is no trap here.");
261 	return 1;
262 }
263 
UseCreate(XCreature * user)264 int XSkill::UseCreate(XCreature * user)
265 {
266 	return 1;
267 }
268 
269 
270