-
Notifications
You must be signed in to change notification settings - Fork 0
/
spells.py
166 lines (121 loc) · 4.03 KB
/
spells.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
from typing import Tuple
from action import SingleTargetAction, ZeroTargetAction, Action
from random import randint, choice
from verb import StandardVerb
import trait
from game_object import Thing
class Spell(Action):
class VerbClass(StandardVerb):
match_strings = [
"cast? VERB",
"cast? VERB on? TARGET",
"cast? VERB on? TARGET with TOOL",
]
def match_quality(self, i):
if i == 3:
return "bad"
else:
return super().match_quality(i)
stamina_cost = 5
def expend_components(self, dry_run : bool):
return (True, "")
def is_valid(self):
try:
known = (type(self) in self.actor.spells_known)
except AttributeError:
known = False
if not known:
return False, "You don't know that spell."
(components_okay, explanation) = self.expend_components(
dry_run=True
)
if not components_okay:
return False, explanation
if self.mana_cost > self.actor.body.mana:
return False, "You don't have enough mana."
return super().is_valid()
def get_name(self, viewer=None):
out = "cast" + self.possible_s(viewer) + " " + self.synonyms[0]
if len(self.target_list) > 0:
out += " on"
return out
def spell_effect(self):
pass
def affect_game(self):
self.expend_components(
dry_run=False
)
self.spell_effect()
class InvalidSpell(Spell, ZeroTargetAction):
synonyms = ["hocus pocus"]
class VerbClass(StandardVerb):
match_strings = ["cast NONSENSE"]
def match_quality(self, i):
return "bad"
class Heal(Spell, SingleTargetAction):
synonyms = ["heal"]
mana_cost = 40
target_traits = [trait.person]
def expend_components(self, dry_run : bool) -> Tuple[bool, str]:
meat = None
for item in self.actor.things_with_trait(trait.meat):
meat = item
break
if meat is None:
return False, "You have no meat to use for the spell."
if not dry_run:
item.vanish()
return (True, "")
def spell_effect(self):
self.target.reset_body()
class Shock(Spell, SingleTargetAction):
synonyms = ["shock"]
mana_cost = 25
def spell_effect(self):
self.target.take_damage(randint(75, 125), "lightning", perpetrator=self.actor)
class Blade(Spell, SingleTargetAction):
synonyms = ["blade"]
mana_cost = 30
def spell_effect(self):
self.target.take_damage(randint(75, 125), "sharp", perpetrator=self.actor)
class Knock(Spell, SingleTargetAction):
synonyms = ["knock"]
mana_cost = 30
def spell_effect(self):
self.target.take_damage(randint(50, 100), "blunt", perpetrator=self.actor)
class AOESpell(Spell, ZeroTargetAction):
affects_caster = False
def spell_effect(self):
for actor in self.actor.location.things_with_trait(trait.actor):
if actor != self.actor or self.affects_caster:
self.affect_object_in_range(actor)
def affect_object_in_range(self, other):
pass
class Sleep(AOESpell):
synonyms = ["sleep"]
mana_cost = 35
def affect_object_in_range(self, other):
duration = randint(20, 30)
other.take_ko(duration)
class Fireball(AOESpell):
synonyms = ["fireball", "fire ball"]
mana_cost = 40
def affect_object_in_range(self, other):
damage = randint(50, 100)
other.take_damage(damage, "fire", perpetrator=self.actor)
class ShockWave(AOESpell):
synonyms = ["shockwave", "shock wave"]
mana_cost = 30
def affect_object_in_range(self, other):
damage = randint(30, 75)
other.take_damage(damage, "blunt", perpetrator=self.actor)
def get_random_spell():
# placeholder, should have procgen later
return choice([
Sleep,
Fireball,
Shock,
Blade,
Knock,
Heal,
])