ardentryst-1.71/ 0000755 0001750 0001750 00000000000 11232757116 013544 5 ustar vincent vincent ardentryst-1.71/Sounds/ 0000755 0001750 0001750 00000000000 11232757116 015017 5 ustar vincent vincent ardentryst-1.71/Demos/ 0000755 0001750 0001750 00000000000 11232757116 014613 5 ustar vincent vincent ardentryst-1.71/Levels/ 0000755 0001750 0001750 00000000000 11232757116 014776 5 ustar vincent vincent ardentryst-1.71/Data/ 0000755 0001750 0001750 00000000000 11232757116 014415 5 ustar vincent vincent ardentryst-1.71/Fonts/ 0000755 0001750 0001750 00000000000 11232757116 014635 5 ustar vincent vincent ardentryst-1.71/Base/ 0000755 0001750 0001750 00000000000 11232757116 014416 5 ustar vincent vincent ardentryst-1.71/Screenshots/ 0000755 0001750 0001750 00000000000 11232757116 016044 5 ustar vincent vincent ardentryst-1.71/Saves/ 0000755 0001750 0001750 00000000000 11232757116 014625 5 ustar vincent vincent ardentryst-1.71/Music/ 0000755 0001750 0001750 00000000000 11232757116 014624 5 ustar vincent vincent ardentryst-1.71/Sounds/NYX/ 0000755 0001750 0001750 00000000000 11232757116 015475 5 ustar vincent vincent ardentryst-1.71/Sounds/PYR/ 0000755 0001750 0001750 00000000000 11232757116 015471 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/ 0000755 0001750 0001750 00000000000 11232757116 017642 5 ustar vincent vincent ardentryst-1.71/Data/Items/ 0000755 0001750 0001750 00000000000 11232757116 015476 5 ustar vincent vincent ardentryst-1.71/Data/StorySceneImages/ 0000755 0001750 0001750 00000000000 11232757116 017641 5 ustar vincent vincent ardentryst-1.71/Data/Magic/ 0000755 0001750 0001750 00000000000 11232757116 015435 5 ustar vincent vincent ardentryst-1.71/Data/ObjectIcons/ 0000755 0001750 0001750 00000000000 11232757116 016617 5 ustar vincent vincent ardentryst-1.71/Data/Numbers/ 0000755 0001750 0001750 00000000000 11232757116 016030 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/ 0000755 0001750 0001750 00000000000 11232757116 017202 5 ustar vincent vincent ardentryst-1.71/Data/InvItems/ 0000755 0001750 0001750 00000000000 11232757116 016153 5 ustar vincent vincent ardentryst-1.71/Data/NPCs/ 0000755 0001750 0001750 00000000000 11232757116 015220 5 ustar vincent vincent ardentryst-1.71/Data/tiles/ 0000755 0001750 0001750 00000000000 11232757116 015535 5 ustar vincent vincent ardentryst-1.71/Data/Nyx/ 0000755 0001750 0001750 00000000000 11232757116 015173 5 ustar vincent vincent ardentryst-1.71/Data/Pyralis/ 0000755 0001750 0001750 00000000000 11232757116 016040 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/poispod/ 0000755 0001750 0001750 00000000000 11232757116 021317 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/snowbat/ 0000755 0001750 0001750 00000000000 11232757116 021317 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/wasp/ 0000755 0001750 0001750 00000000000 11232757116 020614 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/cspider/ 0000755 0001750 0001750 00000000000 11232757116 021273 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/giantworm/ 0000755 0001750 0001750 00000000000 11232757116 021651 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/spider/ 0000755 0001750 0001750 00000000000 11232757116 021130 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/worm/ 0000755 0001750 0001750 00000000000 11232757116 020626 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/snowogre/ 0000755 0001750 0001750 00000000000 11232757116 021505 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/giantjelly/ 0000755 0001750 0001750 00000000000 11232757116 022004 5 ustar vincent vincent ardentryst-1.71/Sounds/MonsterSounds/pod/ 0000755 0001750 0001750 00000000000 11232757116 020424 5 ustar vincent vincent ardentryst-1.71/Data/Magic/implosion1/ 0000755 0001750 0001750 00000000000 11232757116 017527 5 ustar vincent vincent ardentryst-1.71/Data/Magic/fire1/ 0000755 0001750 0001750 00000000000 11232757116 016443 5 ustar vincent vincent ardentryst-1.71/Data/Magic/ice2/ 0000755 0001750 0001750 00000000000 11232757116 016257 5 ustar vincent vincent ardentryst-1.71/Data/Magic/ice1/ 0000755 0001750 0001750 00000000000 11232757116 016256 5 ustar vincent vincent ardentryst-1.71/Data/Magic/burst/ 0000755 0001750 0001750 00000000000 11232757116 016574 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/boss_radkelu/ 0000755 0001750 0001750 00000000000 11232757116 021657 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/poispod/ 0000755 0001750 0001750 00000000000 11232757116 020657 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/snowbat/ 0000755 0001750 0001750 00000000000 11232757116 020657 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/wasp/ 0000755 0001750 0001750 00000000000 11232757116 020154 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/cspider/ 0000755 0001750 0001750 00000000000 11232757116 020633 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/giantworm/ 0000755 0001750 0001750 00000000000 11232757116 021211 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/spider/ 0000755 0001750 0001750 00000000000 11232757116 020470 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/worm/ 0000755 0001750 0001750 00000000000 11232757116 020166 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/snowogre/ 0000755 0001750 0001750 00000000000 11232757116 021045 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/giantjelly/ 0000755 0001750 0001750 00000000000 11232757116 021344 5 ustar vincent vincent ardentryst-1.71/Data/MonsterFrames/pod/ 0000755 0001750 0001750 00000000000 11232757116 017764 5 ustar vincent vincent ardentryst-1.71/Data/NPCs/Frames/ 0000755 0001750 0001750 00000000000 11232757116 016435 5 ustar vincent vincent ardentryst-1.71/Data/NPCs/Faces/ 0000755 0001750 0001750 00000000000 11232757116 016241 5 ustar vincent vincent ardentryst-1.71/Data/Pyralis/backup/ 0000755 0001750 0001750 00000000000 11232757116 017305 5 ustar vincent vincent ardentryst-1.71/Data/NPCs/Frames/Pyralis_Mentor/ 0000755 0001750 0001750 00000000000 11232757116 021404 5 ustar vincent vincent ardentryst-1.71/Data/NPCs/Frames/Nyx_Mentor/ 0000755 0001750 0001750 00000000000 11232757116 020537 5 ustar vincent vincent ardentryst-1.71/Data/NPCs/Frames/Ninja/ 0000755 0001750 0001750 00000000000 11232757116 017474 5 ustar vincent vincent ardentryst-1.71/OPR.txt 0000644 0001750 0001750 00000002015 11113353720 014732 0 ustar vincent vincent Ardentryst Online Play
You may read this at any time from the main menu, and feel free to skip this if you do not intend
to submit your score to the score server.
Rules
By submitting your score to the Ardentryst Online Scoreboard, you agree to these rules:
1. The score is sent from the unaltered Ardentryst game (including its game data files)
2. The score is attained solely by human player(s).
3. You will not use a player name that is derogatory, offensive or anything unsuitable
for a worldwide audience.
4. There is a chance that the score server flags your score submission as invalid when
it is legitimate. Disqualification is not permenant, e-mail me and we can sort it out.
(If this happens, it is a bug in the server code, not a flaw in the algorithm.)
Failure to abide by these rules will result in exclusion of a rank in the scoreboard.
Other than that, you are encouraged to read and edit the source code for your own purpose
(as long as you don't submit a score from that version of the game.)
Press a key.
ardentryst-1.71/enemyai.py 0000644 0001750 0001750 00000120634 11202133451 015536 0 ustar vincent vincent #------------------------------------------------------------------------
#
# This file is part of Ardentryst.
#
# Ardentryst is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ardentryst is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ardentryst. If not, see .
#
# Copyright 2007, 2008, 2009 Jordan Trudgett
#
#------------------------------------------------------------------------
import random, pygame, math
def monster_ground_at(x, l, f=1):
"Finds the y co-ordinate of the ground at position x. For monsters."
x = int(x)
LEVEL = l
ysense = 479
sensing = True
while sensing:
sensetile = LEVEL.map[x/40][ysense/40]
if not sensetile or "NONE" in sensetile.collidetype: break
if sensetile.collidetype == "RIGHT_INCLINATION":
if x%40 < 40-(ysense%40):
break
elif sensetile.collidetype == "RIGHT_HINCLINATION1":
if x%40 < 2*(40-(ysense%40)):
break
elif sensetile.collidetype == "RIGHT_HINCLINATION2":
if (x%40)+40 < 2*(40-(ysense%40)):
break
elif sensetile.collidetype == "LEFT_INCLINATION":
if x%40 > ysense%40:
break
elif sensetile.collidetype == "LEFT_HINCLINATION1":
if x%40 + 40 > 2*(ysense%40):
break
elif sensetile.collidetype == "LEFT_HINCLINATION2":
if (x%40) > 2*(ysense%40):
break
ysense -= f
if ysense == 479: return 666 # Has to be greater than 500
return ysense
class Monster:
def __init__(self):
# Vitals
self.name = "?????"
self.presentable_name = "?????"
self.x = 0
self.y = 0
self.a_prefix = ""
self.a_frame = 1
self.ticker = 0
self.diedyet = False
self.isdead = False
self.collision_dist = 30
self.collision_hdist = 40 #height
self.active = False
self.PLAYDEMO = False
# Self's stats
self.hp = 0
self.maxhp = 0
self.projectile_damage = 5
self.ghost = False
self.affected = {"quake": False}
# Rewards
self.reward_exp = 0
self.reward_hp = [0]
self.reward_items = []
# Visuals
self.numbers = []
self.projectiles = []
# Contact to the outside world
self.chimed = False
self.useprojectilecollision = True
self.SOUND = ""
self.SOUNDTIME = 0
self.AFTERSOUND = 5
self.REMOVEME = False
self.SPAWN_GOODIES = False
self.ALPHA = 255
self.FLIPME = False
self.EXECUTE = ""
self.BOSS = False
self.slayercount = False
self.PLAYERSTATE = None
self.LEVELSTATE = None
def inscreen(self, CX):
if CX - 50 <= self.x <= CX + 690:
return True
return False
def update(self, x, y):
self.x = x
self.y = y
def info(self, pl, lv):
self.PLAYERSTATE = pl
self.LEVELSTATE = lv
def step(self):
return
def die(self):
return
def tick(self):
if self.SOUNDTIME > 0: self.SOUNDTIME -= 1
self.ticker += 1
if self.hp <= 0:
if not self.diedyet:
self.die()
self.diedyet = True
self.step()
def damage(self):
return
def collision(self, entity):
return
def react_to_damage(self, damage):
if damage > self.maxhp:
damage = self.maxhp
if damage > self.hp:
damage = self.hp
if self.isdead: return
curative = False
if damage < 0:
curative = True
damage = [str(damage),str(damage)[1:]][curative]
damage = str(int(round(float(damage))))
if not damage.isdigit():
print "Damage was not a digit!"
return
num_info = [curative]
phase = 0
bounce_height = 40
for digit in damage:
num_info.append(
[digit, phase, bounce_height]
)
phase += 1
if not self.PLAYDEMO:
self.numbers.append(num_info)
self.hp -= int(float(damage))
if self.hp > 0:
self.damage()
def react_to_magic(self, damage):
if damage > self.maxhp:
damage = self.maxhp
if damage > self.hp:
damage = self.hp
if self.isdead: return
curative = False
if damage < 0:
curative = True
damage = [str(damage),str(damage)[1:]][curative]
damage = str(int(round(float(damage))))
if not damage.isdigit():
print "Damage was not a digit!"
return
num_info = [curative]
phase = 0
bounce_height = 40
for digit in damage:
num_info.append(
[digit, phase, bounce_height]
)
phase += 1
self.numbers.append(num_info)
self.hp -= int(float(damage))
if self.hp > 0:
self.damage()
def Advance_Numbers(self):
for i in range(len(self.numbers)):
for j in range(len(self.numbers[i])):
if j == 0: continue
self.numbers[i][j][1] += 1.5
if self.numbers[i][j][1] >= 84:
self.numbers[i] = None
break
while None in self.numbers:
self.numbers.remove(None)
class pod(Monster):
def m_init(self):
self.name = "pod"
self.presentable_name = "Nepthene"
self.hp = 40
self.maxhp = self.hp
self.reward_exp = 5
self.reward_hp = [6, 2, 3, 5,
1, 3, 10]
self.reward_mp = [2, 2, 4,
]
self.reward_items = [
(55, "Nepthene tongue"),
(1, "Nepthene fibre leggings")]
self.a_prefix = "rest"
self.a_frame = 1
self.barb_pain = 4
self.collision_dist = 25
self.barbtime = 0
self.rechargehp = 0
self.affected["quake"] = True
def step(self):
if self.isdead:
self.a_prefix = "hurt"
self.a_frame = 1
self.ticker = 0
self.ALPHA -= 8
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
self.rechargehp += 0.08
if self.rechargehp >= 1:
self.rechargehp = 0
self.hp += 1
if self.hp > self.maxhp:
self.hp = self.maxhp
if self.barbtime: self.barbtime -= 1
if not self.ticker%16:
self.a_prefix = "rest"
self.a_frame += 1
if self.a_frame >= 3:
self.a_frame = 1
def die(self):
self.SOUND = "death"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.a_prefix = "hurt"
self.ticker = 8
self.SOUND = "hurt"
self.AFTERSOUND = 6
def collision(self, entity):
if entity.x > self.x: entity.inertia[0] = random.randint(3,6)
else: entity.inertia[0] = random.randint(-6,-3)
if not self.barbtime:
entity.raw_hit(self.barb_pain * (random.randint(60,140)/100.0))
self.barbtime = 20
self.SOUND = "barb"
class poispod(Monster):
def m_init(self):
self.name = "poispod"
self.presentable_name = "Venom Nepthene"
self.hp = 85
self.maxhp = self.hp
self.reward_exp = 18
self.reward_hp = [7, 9, 8, 10,
5, 7, 14, 0]
self.reward_mp = [4, 7, 6, 0, 0
]
self.reward_items = [(50, "Nepthene tongue")]
self.a_prefix = "rest"
self.a_frame = 1
self.barb_pain = 10
self.collision_dist = 25
self.barbtime = 0
self.rechargehp = 0
self.affected["quake"] = True
self.gasdown = 0
def step(self):
if self.isdead:
self.a_prefix = "hurt"
self.a_frame = 1
self.ticker = 0
self.ALPHA -= 8
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
if self.gasdown:
self.gasdown -= 1
if self.gasdown == 1:
self.EXECUTE = "Objects.append(Gas(" + str(self.x) + "," + str(self.y - 6) + "))"
self.rechargehp += 0.16
if self.rechargehp >= 1:
self.rechargehp = 0
self.hp += 1
if self.hp > self.maxhp:
self.hp = self.maxhp
if self.barbtime: self.barbtime -= 1
if not self.ticker%120:
self.gasdown = 25
if self.gasdown > 0:
self.a_prefix = "rest"
self.a_frame = 3
elif not self.ticker%16:
self.a_prefix = "rest"
self.a_frame += 1
if self.a_frame >= 3:
self.a_frame = 1
def die(self):
self.SOUND = "death"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.a_prefix = "hurt"
self.ticker = 8
self.SOUND = "hurt"
self.AFTERSOUND = 6
def collision(self, entity):
if random.randint(0, 4) == 0: entity.bits["poisoned"] = True
if entity.x > self.x: entity.inertia[0] = random.randint(3,6)
else: entity.inertia[0] = random.randint(-6,-3)
if not self.barbtime:
entity.raw_hit(self.barb_pain * (random.randint(60,140)/100.0))
self.barbtime = 30
self.SOUND = "barb"
class spider(Monster):
def m_init(self):
self.name = "spider"
self.presentable_name = "Forest Arex"
self.hp = 20
self.maxhp = self.hp
self.reward_exp = 3
self.reward_hp = [2, 1, 3, 2,
0, 0, 0]
self.reward_mp = [1, 0, 0,
]
self.reward_items = []
self.a_prefix = "rest"
self.a_frame = 1
self.collision_dist = 20
self.collision_hdist = 40
self.hittime = 0
self.upjump = 0
self.basex = 0
self.basey = 0
self.angle = 1.5 * math.pi
self.swing = 0
def step(self):
if self.isdead:
self.ticker = 1
self.ALPHA -= 8
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
if self.basey == 0: self.basey = self.y
if self.basex == 0: self.basex = self.x
if self.upjump > 1:
self.basey -= self.upjump
self.upjump *= 0.9
else:
self.upjump = 0
if self.hittime > 0: self.hittime -= 1
if self.basey < self.PLAYERSTATE.y:
self.basey += 2
elif self.y - 5 > self.PLAYERSTATE.y:
if self.upjump == 0:
self.upjump = 7
mga = monster_ground_at(self.x, self.LEVELSTATE, 8)
if mga > self.y - 20:
self.y = min(-(math.sin(self.angle) * self.basey), mga-10)
self.x = self.basex + math.cos(self.angle) * self.basey
if abs(self.swing) > 0.01:
self.angle += 0.01*self.swing
self.swing *= 0.8
else:
self.swing = 0
if self.angle > 1.53*math.pi:
self.swing -= 0.11
elif self.angle < 1.47*math.pi:
self.swing += 0.11
if not self.ticker%16:
self.a_frame +=1
if self.a_frame == 3:
self.a_frame = 1
def die(self):
self.isdead = True
self.SPAWN_GOODIES = True
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/40
self.SOUND = "squeak"
def damage(self):
self.AFTERSOUND = 6
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/40
self.SOUND = "squeak"
def collision(self, entity):
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/40
if not self.hittime:
entity.raw_hit(random.randint(1,2))
self.hittime = 24
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/24
class cspider(Monster):
def m_init(self):
self.name = "cspider"
self.presentable_name = "Arex"
self.hp = 20
self.maxhp = self.hp
self.reward_exp = 3
self.reward_hp = [3, 3, 5, 3,
1, 1, 1]
self.reward_mp = [3, 1, 1,
]
self.reward_items = []
self.a_prefix = "rest"
self.a_frame = 1
self.collision_dist = 20
self.collision_hdist = 40
self.hittime = 0
self.upjump = 0
self.basex = 0
self.basey = 0
self.angle = 1.5 * math.pi
self.swing = 0
def step(self):
if self.isdead:
self.ticker = 1
self.ALPHA -= 8
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
if self.basey == 0: self.basey = self.y
if self.basex == 0: self.basex = self.x
if self.upjump > 1:
self.basey -= self.upjump
self.upjump *= 0.9
else:
self.upjump = 0
if self.hittime > 0: self.hittime -= 1
if self.basey < self.PLAYERSTATE.y:
self.basey += 2
elif self.y - 5 > self.PLAYERSTATE.y:
if self.upjump == 0:
self.upjump = 7
mga = monster_ground_at(self.x, self.LEVELSTATE, 8)
if mga > self.y - 20:
self.y = min(-(math.sin(self.angle) * self.basey), mga-10)
self.x = self.basex + math.cos(self.angle) * self.basey
if abs(self.swing) > 0.01:
self.angle += 0.01*self.swing
self.swing *= 0.8
else:
self.swing = 0
if self.angle > 1.53*math.pi:
self.swing -= 0.11
elif self.angle < 1.47*math.pi:
self.swing += 0.11
if not self.ticker%16:
self.a_frame +=1
if self.a_frame == 3:
self.a_frame = 1
def die(self):
self.isdead = True
self.SPAWN_GOODIES = True
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/40
self.SOUND = "squeak"
def damage(self):
self.AFTERSOUND = 6
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/40
self.SOUND = "squeak"
def collision(self, entity):
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/40
if not self.hittime:
entity.raw_hit(random.randint(1,3))
self.hittime = 24
self.swing = cmp(self.x, self.PLAYERSTATE.x) * (480-self.basey)/24
class giantjelly(Monster):
def m_init(self):
self.name = "giantjelly"
self.presentable_name = "Gelatice"
self.hp = 200
self.maxhp = self.hp
self.reward_exp = 25
self.reward_hp = [9, 11, 11, 6,
12, 4, 12, 0, 0]
self.reward_mp = [7, 7, 4, 0, 0
]
self.reward_items = [(50, "Potion2"),
(40, "Mana potion"),
(5, "Haste ring")]
self.a_prefix = "move"
self.a_frame = 1
self.pain = 8
self.inert = 0
self.fall = 0
self.collision_dist = 50
self.collision_hdist = 70
self.hittime = 0
self.sling = True
self.slingt = 0
# self.imgheight = 40
self.affected["quake"] = True
def step(self):
if self.isdead:
self.a_prefix = "hurt"
self.a_frame = 1
self.ticker = 0
self.ALPHA -= 6
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
p = self.PLAYERSTATE
if p.x - self.x < 700 and self.sling:
if p.x < self.x and self.inert > -3:
self.inert -= 0.5
elif p.x > self.x and self.inert < 3:
self.inert += 0.5
self.slingt += 1
if self.slingt >= 40 and self.sling or self.slingt >= 10 and not self.sling:
self.slingt = 0
self.sling = not self.sling
self.a_prefix = "move"
self.a_frame = self.sling + 1
self.y += self.fall
self.FLIPME = self.PLAYERSTATE.x > self.x
mga = monster_ground_at(self.x+self.inert, self.LEVELSTATE, 2)
mgaf = monster_ground_at(self.x+15*cmp(self.inert, 0), self.LEVELSTATE, 3)
if mga > self.y - 5:
if mgaf > self.y - 25:
self.x += self.inert
if abs(mga - self.y) < 6:
self.y = mga+2
self.fall = 0
else:
self.fall = min(5, self.fall + 0.5)
if mgaf < self.y - 25:
self.inert = 0
self.inert *= 0.85
if self.hittime:
self.hittime -= 1
if self.y > 500:
self.hp = 0
def die(self):
self.SOUND = "hurt"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.a_prefix = "hurt"
self.ticker = 8
self.SOUND = "hurt"
self.AFTERSOUND = 6
if self.PLAYERSTATE.x < self.x:
self.inert += 2
else:
self.inert -= 2
def collision(self, entity):
if entity.x > self.x: entity.inertia[0] = random.randint(4,8); self.inert -= .5
else: entity.inertia[0] = random.randint(-8,-4); self.inert += .5
if not self.hittime:
entity.raw_hit(self.pain * (random.randint(60,140)/100.0))
self.hittime = 10
self.SOUND = "collide"
class worm(Monster):
def m_init(self):
self.name = "worm"
self.presentable_name = "Anneludine"
self.hp = 70
self.maxhp = self.hp
self.reward_exp = 10
self.reward_hp = [6, 8, 3, 6,
1, 3, 12, 0, 0, 0, 0]
self.reward_mp = [5, 5, 4,
]
self.reward_items = [(60, "Anneludine shell"),
(42, "Potion"),
(26, "Mana potion"),
(2, "Silver ring")]
self.a_prefix = "move"
self.a_frame = 1
self.pain = 6
self.inert = 0
self.fall = 0
self.hittime = 0
self.affected["quake"] = True
def step(self):
if self.isdead:
self.a_prefix = "hurt"
self.a_frame = 1
self.ticker = 0
self.ALPHA -= 8
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
p = self.PLAYERSTATE
if p.x - self.x < 700:
if p.x < self.x and self.inert > -1.5:
self.inert -= 0.05
elif p.x > self.x and self.inert < 1.5:
self.inert += 0.05
if not self.ticker%14:
self.a_prefix = "move"
self.a_frame = (self.a_frame % 2) + 1
self.y += self.fall
self.FLIPME = self.PLAYERSTATE.x > self.x
mga = monster_ground_at(self.x+self.inert, self.LEVELSTATE, 2)
mgaf = monster_ground_at(self.x+15*cmp(self.inert, 0), self.LEVELSTATE, 3)
if mga > self.y - 5:
if mgaf > self.y - 25:
self.x += self.inert
if abs(mga - self.y) < 6:
self.y = mga+2
self.fall = 0
else:
self.fall = min(5, self.fall + 0.5)
if mgaf < self.y - 25:
self.inert = 0
self.inert *= 0.96
if self.hittime:
self.hittime -= 1
if self.y > 500:
self.hp = 0
def die(self):
self.SOUND = "hurt"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.a_prefix = "hurt"
self.ticker = 8
self.SOUND = "hurt"
self.AFTERSOUND = 6
if self.PLAYERSTATE.x < self.x:
self.inert += 4
else:
self.inert -= 4
def collision(self, entity):
if entity.x > self.x: entity.inertia[0] = random.randint(2,4); self.inert -= 2
else: entity.inertia[0] = random.randint(-4,-2); self.inert += 2
if not self.hittime:
entity.raw_hit(self.pain * (random.randint(60,140)/100.0))
self.hittime = 20
self.SOUND = "collide"
class wasp(Monster):
def m_init(self):
self.name = "wasp"
self.presentable_name = "Wasp"
self.hp = 50
self.maxhp = self.hp
self.reward_exp = 7
self.reward_hp = [6, 4, 0, 0]
self.reward_mp = [2, 0, 0]
self.reward_items = []
self.a_prefix = "fly"
self.a_frame = 1
self.collision_dist = 20
self.collision_hdist = 20
self.pain = 5
self.sx = self.x-20
self.sy = self.y
self.hittime = 0
self.fall = 0
self.xdash = 0
self.pause = 0
def step(self):
if self.isdead:
self.a_prefix = "dead"
self.a_frame = 1
self.ticker = 0
self.fall += 0.5
self.y += self.fall
self.x += self.xdash
if self.y >= 500: self.REMOVEME = True
else:
if self.pause: self.ticker -= 1; self.pause -= 1
ox = self.x
self.FLIPME = self.PLAYERSTATE.x > self.x
self.x = int(self.sx + 40 * math.cos(self.ticker/11.0))
self.xdash = self.x-ox
self.y = int(self.sy + 30 * math.sin(self.ticker/11.0))
if not self.ticker%4 or self.pause:
self.a_prefix = "fly"
self.a_frame += 1
if self.a_frame >= 5:
self.a_frame = 1
if self.hittime:
self.hittime -= 1
def die(self):
self.SOUND = "dead"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.SOUND = "hurt"
self.AFTERSOUND = 6
self.pause = 12
def collision(self, entity):
if entity.x > self.x: entity.inertia[0] = random.randint(1,2)
else: entity.inertia[0] = random.randint(-2,-1)
if not self.hittime:
entity.raw_hit(self.pain * (random.randint(60,140)/100.0))
self.hittime = 12
self.SOUND = "hurt"
class giantworm(Monster):
def m_init(self):
self.name = "giantworm"
self.presentable_name = "Mega Annelud."
self.hp = 450
self.maxhp = self.hp
self.reward_exp = 50
self.reward_hp = [30, 24, 20, 26,
19, 23, 17]
self.reward_mp = [30, 33, 24,
]
self.reward_items = [(80, "Mega anneludine skull"),
(10, "Regen ring"),
(5, "Haste ring"),
(4, "Nature pendant"),
(1, "Ancient pendant")]
self.a_prefix = "move"
self.a_frame = 1
self.projectile_damage = 12
self.pain = 20
self.inert = 0
self.collision_dist = 100
self.collision_hdist = 120
self.Active = False
self.hittime = 0
self.affected["quake"] = True
self.lasty = None
def step(self):
if self.isdead:
self.a_frame = 1
self.ticker = 0
self.ALPHA -= 2
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
p = self.PLAYERSTATE
if p.x - self.x < 700:
if p.x < self.x and self.inert > -1:
self.inert -= 0.05
if not self.ticker%24:
self.a_prefix = "move"
self.a_frame = (self.a_frame % 2) + 1
if not self.ticker%120:
self.projectiles.append(["slimeball.png", self.x-70, self.y-60, 100])
self.SOUND = "belch"
for p in range(len(self.projectiles)):
if self.projectiles[p] is None: continue
self.projectiles[p][3] -= 1
self.projectiles[p][1] -= 3
theg = monster_ground_at(self.projectiles[p][1], self.LEVELSTATE)
if self.projectiles[p][2] - (theg-25) > 40:
self.projectiles[p] = None
else:
self.projectiles[p][2] = min(self.projectiles[p][2] + 2, theg-25)
while None in self.projectiles:
self.projectiles.remove(None)
self.FLIPME = self.PLAYERSTATE.x > self.x
self.inert *= 0.99
newy = monster_ground_at(self.x, self.LEVELSTATE)
if self.lasty:
if abs(self.lasty-newy) < 40:
self.y = newy
self.x += self.inert
else:
self.inert = 0
else:
self.y = newy
if not self.lasty:
self.lasty = self.y
if self.hittime:
self.hittime -= 1
def die(self):
self.SOUND = "dead"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.ticker = 8
self.SOUND = "hurt"
self.AFTERSOUND = 24
def collision(self, entity):
if entity.x > self.x: entity.inertia[0] = random.randint(10,16); self.inert = 0
else: entity.inertia[0] = random.randint(-16,-10); self.inert = 0
if not self.hittime:
entity.raw_hit(self.pain * (random.randint(60,140)/100.0))
self.hittime = 30
self.SOUND = "collide"
def inscreen(self, CX):
if self.x <= CX + 900: self.Active = True
return self.Active
# Snodom
class snowogre(Monster):
def m_init(self):
self.name = "snowogre"
self.presentable_name = "Snought"
self.hp = 130
self.maxhp = self.hp
self.reward_exp = 20
self.reward_hp = [11, 10, 8, 10,
1, 3, 22, 0, 0, 0, 0]
self.reward_mp = [0, 0, 7,
]
self.reward_items = [(90, "Potion"),
(40, "Mana potion"),
(2, "Regen ring")]
self.a_prefix = "rest"
self.a_frame = 1
self.ghost = True
self.pain = 8
self.inert = 0
self.fall = 0
self.collision_hdist = 60
self.hittime = 0
self.state = 0 #0:rest, 1:walking, 2:charging, 3:lunging
self.rising = False
self.charging = 0
self.lunged = False
self.affected["quake"] = True
def step(self):
if self.isdead:
self.a_frame = 5
self.a_prefix = "walk"
self.ticker = 0
self.ALPHA -= 6
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
p = self.PLAYERSTATE
if p.x > self.x + 80 and not self.rising:
self.rising = True
if self.rising and not self.ticker%4 and self.a_prefix == "rest":
if self.a_frame == 4:
self.rising = False
self.a_prefix = "walk"
self.a_frame = 1
self.state = 1
self.ghost = False
else:
self.a_frame += 1
if self.state == 1:
if p.x - self.x < 700:
if p.x < self.x and self.inert > -4:
self.inert -= 0.25
elif p.x > self.x and self.inert < 4:
self.inert += 0.25
if not self.ticker%7:
self.a_prefix = "walk"
self.a_frame = (self.a_frame % 6) + 1
if abs(p.x - self.x) < 250:
self.state = 2
self.charging = 0
if self.state == 2:
self.charging += 1
self.a_prefix = "attack"
self.a_frame = 1
self.FLIPME = self.PLAYERSTATE.x > self.x
if self.charging >= 30:
self.state = 3
self.FLIPME = self.PLAYERSTATE.x > self.x
if self.state == 3:
if self.lunged == False:
self.lunged = True
self.a_prefix = "attack"
self.a_frame = 2
if self.FLIPME:
self.inert = 8
else:
self.inert = -8
if abs(self.inert) < 4 and self.state == 3: self.lunged = False; self.state = 1
self.y += self.fall
if self.state == 1: self.FLIPME = self.PLAYERSTATE.x > self.x
mga = monster_ground_at(self.x+self.inert, self.LEVELSTATE, 2)
mgaf = monster_ground_at(self.x+15*cmp(self.inert, 0), self.LEVELSTATE, 3)
if mga > self.y - 15:
if mgaf > self.y - 25:
self.x += self.inert
if abs(mga - self.y) < 15:
self.y = mga+2
self.fall = 0
else:
self.fall = min(5, self.fall + 0.5)
if mgaf < self.y - 25:
self.inert = 0
self.inert *= 0.98
if self.hittime:
self.hittime -= 1
if self.y > 500:
self.hp = 0
def react_to_damage(self, damage):
if self.state == 0: return
if damage > self.maxhp:
damage = self.maxhp
if damage > self.hp:
damage = self.hp
if self.isdead: return
curative = False
if damage < 0:
curative = True
damage = [str(damage),str(damage)[1:]][curative]
damage = str(int(round(float(damage))))
if not damage.isdigit():
print "Damage was not a digit!"
return
num_info = [curative]
phase = 0
bounce_height = 40
for digit in damage:
num_info.append(
[digit, phase, bounce_height]
)
phase += 1
self.numbers.append(num_info)
self.hp -= int(float(damage))
if self.hp > 0:
self.damage()
self.SOUND = "hurt"
def react_to_magic(self, damage):
if self.state == 0: return
if damage > self.maxhp:
damage = self.maxhp
if damage > self.hp:
damage = self.hp
if self.isdead: return
curative = False
if damage < 0:
curative = True
damage = [str(damage),str(damage)[1:]][curative]
damage = str(int(round(float(damage))))
if not damage.isdigit():
print "Damage was not a digit!"
return
num_info = [curative]
phase = 0
bounce_height = 40
for digit in damage:
num_info.append(
[digit, phase, bounce_height]
)
phase += 1
self.numbers.append(num_info)
self.hp -= int(float(damage))
if self.hp > 0:
self.damage()
self.SOUND = "hurt"
def die(self):
# self.SOUND = "hurt"
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.a_frame = 1
self.a_prefix = "walk"
self.ticker = 0
# self.SOUND = "hurt"
# self.AFTERSOUND = 6
self.inert = 0
def collision(self, entity):
if self.state == 0: return
if self.state == 1 or self.state == 2: entity.inertia[0] = (((int(entity.x>self.x))*2)-1)*3; self.inert = 0; return
# is lunging
if entity.x > self.x: entity.inertia[0] = random.randint(2,4)
else: entity.inertia[0] = random.randint(-4,-2)
if not self.hittime:
entity.raw_hit(self.pain * (random.randint(60,140)/100.0))
self.hittime = 20
# self.SOUND = "collide"
self.state = 1
self.lunged = False
class snowbat(Monster):
def m_init(self):
self.name = "snowbat"
self.presentable_name = "Flust"
self.hp = 80
self.maxhp = self.hp
self.reward_exp = 15
self.reward_hp = [5, 9, 3, 5,
1, 3, 2, 0]
self.reward_mp = [2, 0
]
self.reward_items = [(20, "Potion")]
self.a_prefix = "fly"
self.a_frame = 1
self.collision_dist = 20
self.collision_hdist = 25
self.hittime = 0
self.pain = 2
self.inert = [0, 0]
def step(self):
pl = self.PLAYERSTATE
rt, rt2 = random.randint(-20, 20), random.randint(-20, 20)
if pl.x + rt > self.x:
self.inert[0] += 0.2
self.FLIPME = True
elif pl.x + rt < self.x:
self.inert[0] -= 0.2
if pl.y-35 + rt2 > self.y:
self.inert[1] += 0.2
elif pl.y-35 + rt2 < self.y:
self.inert[1] -= 0.2
self.inert[0] *= 0.96
self.inert[1] *= 0.96
self.x += self.inert[0]
self.y += self.inert[1]
if self.isdead:
self.a_frame = 1
self.ticker = 0
self.ALPHA -= 8
if self.ALPHA <= 0: self.ALPHA = 0; self.REMOVEME = True
else:
if self.hittime:
self.hittime -= 1
self.a_frame = abs(((self.ticker/3)%4)-2) + 1
self.FLIPME = self.PLAYERSTATE.x > self.x
def die(self):
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
self.inert[1] += self.PLAYERSTATE.inertia[1]*0.4
self.SOUND = "squeak"
if self.PLAYERSTATE.direction:
self.inert[0] += 15
else:
self.inert[0] -= 15
def collision(self, entity):
if not self.hittime:
entity.raw_hit(self.pain * (random.randint(60,140)/100.0))
self.hittime = 25
# Bosses
class boss_radkelu(Monster):
def m_init(self):
self.name = "boss_radkelu"
self.presentable_name = "Radkelu"
self.hp = 20000
self.maxhp = self.hp
self.reward_exp = 200
self.reward_hp = [248, 155, 339, 462]
self.reward_mp = [129, 350, 238]
self.reward_items = []
self.a_prefix = "stopped"
self.a_frame = 1
self.collision_dist = 20
self.collision_hdist = 100
self.pain = 5
self.phase = 0
self.ptick = 0
self.f1 = []
self.useprojectilecollision = False
self.fphase = 0
self.fphase2 = 0
self.BOSS = True
self.BOSSFACE = "Radkeluface.png"
def step(self):
if self.isdead:
self.ALPHA -= 5
if self.ALPHA <= 0:
self.PLAYERSTATE.iwin = True
self.REMOVEME = True
else:
if self.phase == 0:
# Not active yet.
self.cx = self.x
self.cy = self.y
if self.PLAYERSTATE.x > 1050 or self.hp < self.maxhp:
self.phase = 1
self.hp = self.maxhp
elif self.phase == 1 or self.phase == 6:
# Sweep left to right, shooting fireballs from hands
self.x = self.cx - math.sin(self.ptick/70.0) * 250
self.ptick += 1
if not self.ptick%8:
if self.fphase == 0:
self.f1.append([self.x - 32, self.y - 68, -3, 6])
self.f1.append([self.x + 28, self.y - 68, 3, 6])
self.fphase = 1
elif self.fphase == 1:
self.f1.append([self.x - 32, self.y - 68, -6, 6])
self.f1.append([self.x + 28, self.y - 68, 6, 6])
self.fphase = 2
elif self.fphase == 2:
self.f1.append([self.x - 32, self.y - 68, -1, 6])
self.f1.append([self.x + 28, self.y - 68, 1, 6])
self.fphase = 0
if self.ptick >= 400:
self.phase = 2
self.ptick = 0
elif self.phase == 2:
# Coming from phase 1, centring for phase 3
self.x = (self.x * 19 + self.cx) / 20.0
self.ptick += 1
if self.ptick >= 100:
self.phase = 3
self.ptick = 0
elif self.phase == 3:
#levitate to centre and shoot fireballs
self.x = self.cx
ra = math.sin(self.ptick/20.0) * 45
langle = math.radians(ra)
rangle = math.radians(-ra)
if not self.ptick%3 and not (self.ptick/8)%3:
self.f1.append([self.x - 32, self.y - 68, 6 * math.sin(langle), 6 * math.cos(langle)])
self.f1.append([self.x + 28, self.y - 68, 6 * math.sin(rangle), 6 * math.cos(rangle)])
self.ptick += 1
if self.ptick >= 600:
self.ptick = 0
self.phase = 4
self.fphase2 = 0
elif self.phase == 4:
self.y = min(int(self.cy + self.ptick*2), 380)
if not self.ptick%5 and not (self.ptick/20)%4:
if self.fphase2 == 0:
self.f1.append([self.x - 32, self.y - 68, -5, 6])
self.f1.append([self.x + 28, self.y - 68, 5, 6])
self.fphase2 = 1
elif self.fphase2 == 1:
self.f1.append([self.x - 32, self.y - 68, -7, 6])
self.f1.append([self.x + 28, self.y - 68, 7, 6])
self.fphase2 = 2
elif self.fphase2 == 2:
self.f1.append([self.x - 32, self.y - 68, -7, 4])
self.f1.append([self.x + 28, self.y - 68, 7, 4])
self.fphase2 = 3
elif self.fphase2 == 3:
self.f1.append([self.x - 32, self.y - 68, -9, 4])
self.f1.append([self.x + 28, self.y - 68, 9, 4])
self.fphase2 = 0
self.ptick += 1
if self.ptick >= 200:
self.ptick = 0
self.phase = 5
elif self.phase == 5:
self.y = max(380 - self.ptick * 2, self.cy)
self.ptick += 1
if self.ptick >= 100:
self.ptick = 0
self.fphase = 0
self.phase = 1
if self.hp < self.maxhp / 2:
if not self.ptick % 4:
self.f1.append([self.x - 1000, self.cy+100, 10, 0])
self.f1.append([self.x + 1000, self.cy+100, -10, 0])
# Tick fireballs
for x in range(len(self.f1)):
self.f1[x][0] += self.f1[x][2]
self.f1[x][1] += self.f1[x][3]
if self.f1[x][1] > 500 or self.f1[x][0] < 0 or self.f1[x][0] > 2560:
self.f1[x] = None
for f in range(len(self.f1)):
if not self.f1[f]: continue
px, py, i1, i2 = self.f1[f]
if abs(px - self.PLAYERSTATE.x) < 12 and abs(py - (self.PLAYERSTATE.y-40)) < 25:
self.f1[f] = None
self.PLAYERSTATE.raw_hit(random.randint(6, 12))
while None in self.f1:
self.f1.remove(None)
# Create projectile array
self.projectiles = []
for x, y, dx, dy in self.f1:
self.projectiles.append(["rfireball.png", x, y])
def die(self):
self.isdead = True
self.SPAWN_GOODIES = True
def damage(self):
pass
def collision(self, entity):
pass
def inscreen(self, x):
return True
ardentryst-1.71/README.txt 0000644 0001750 0001750 00000000153 11073112374 015233 0 ustar vincent vincent Run ardentryst.py with python (preferrably 2.4+) to play.
If you are in need of help, see help.txt!
Enjoy!
ardentryst-1.71/Ardentryst.desktop 0000644 0001750 0001750 00000000255 11232747326 017302 0 ustar vincent vincent [Desktop Entry]
Encoding=UTF-8
Name=Ardentryst
Categories=Game;RolePlaying
Comment=Fantasy sidescroller game
Exec=ardentryst
Terminal=false
Icon=ardentryst
Type=Application
ardentryst-1.71/magic.py 0000644 0001750 0001750 00000054107 11232752774 015212 0 ustar vincent vincent #------------------------------------------------------------------------
#
# This file is part of Ardentryst.
#
# Ardentryst is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ardentryst is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ardentryst. If not, see .
#
# Copyright 2007, 2008, 2009 Jordan Trudgett
#
#------------------------------------------------------------------------
import pygame, math, random
from pygame.locals import *
def ground_at(LEVEL, x, f=False):
"Finds the y co-ordinate of the ground at position x."
ysense = 479
sensing = True
while sensing:
sensetile = LEVEL.map[x/40][ysense/40]
if not sensetile or "NONE" in sensetile.collidetype: break
if sensetile.collidetype == "RIGHT_INCLINATION":
if x%40 < 40-(ysense%40):
break
elif sensetile.collidetype == "RIGHT_HINCLINATION1":
if x%40 < 2*(40-(ysense%40)):
break
elif sensetile.collidetype == "RIGHT_HINCLINATION2":
if (x%40)+40 < 2*(40-(ysense%40)):
break
elif sensetile.collidetype == "LEFT_INCLINATION":
if x%40 > ysense%40:
break
elif sensetile.collidetype == "LEFT_HINCLINATION1":
if x%40 + 40 > 2*(ysense%40):
break
elif sensetile.collidetype == "LEFT_HINCLINATION2":
if (x%40) > 2*(ysense%40):
break
ysense -= [1,10][f]
if ysense <= 0: return 479
return ysense
def m_init_data(data):
global DATA
DATA = data
class Spell: # Spell is a class that (basically) all spells are based on
def __init__(self, caster, x, y):
self.cost = 0
self.x = x
self.y = y
self.caster = caster
self.a_step = 0
self.ticker = 0
self.LEVELSTATE = None
self.MONSTERSTATE = None
self.RAIN_H = False
self.finished = False
self.SOUND = ""
self.fvm = None # Faceview monster
self.fvd = 0 # faceview damage
self.s_init()
def s_init(self):
pass
def blit(self, surf, ALT_X = 0, ALT_Y = 0):
if not self.finished: self.s_blit(surf, ALT_X, ALT_Y)
def tick(self, LEVEL, MONSTERS, CASTER, RAIN = False):
if self.finished: return
self.RAIN_H = RAIN
self.LEVELSTATE = LEVEL
self.MONSTERSTATE = MONSTERS
self.ticker += 1
self.caster = CASTER
self.stick()
class Fire_1(Spell):
def s_init(self):
self.cost = 4
if self.caster.mp[0] < self.cost: self.finished = True; return
self.frames = ["m_fire1_" + str(x) + ".png" for x in range(1,6)]
self.flame_entities = []
self.caster.mbreaktime = 16
self.caster.mp[0] -= self.cost
self.mydir = self.caster.direction * 2 - 1
self.unchdir = self.caster.direction
self.x += self.mydir * 10
self.rise = 0
def s_blit(self, surf, ALT_X, ALT_Y):
c = 0
for flame in self.flame_entities:
if flame == -40: continue
gimg, grect = DATA.mag_images["m_fire1_glow.png"]
img, rect = DATA.mag_images[self.frames[flame%5]]
rect.midbottom = (self.x + flame*8, self.y-math.sin(flame/2.0)*5.0+c*self.rise+((c+0.001)**(abs(self.rise)+1))*[1,-1][self.rise<0])
rect.move_ip(ALT_X, ALT_Y)
grect.midbottom = (self.x + flame*8, self.y-math.sin(flame/2.0)*5.0+c*self.rise+((c+0.001)**(abs(self.rise)+1))*[1,-1][self.rise<0])
grect.move_ip(ALT_X, ALT_Y+3)
surf.blit(img, rect)
surf.blit(gimg, grect)
c += 1
def stick(self):
self.y = self.caster.y - 25
self.x = self.caster.x
self.caster.jumping = False
if len(self.flame_entities) < 8:
self.caster.direction = self.unchdir
if not self.ticker % 2:
if len(self.flame_entities) < 8:
self.flame_entities = [0] + self.flame_entities
self.flame_entities = [[x + self.mydir,-40][[x<-35 or x>0,x>35 or x<0][self.unchdir]] for x in self.flame_entities]
if self.caster.up_held: self.rise -= 0.05
if self.caster.down_held: self.rise += 0.05
# Collision detections
c = 0
for flame in self.flame_entities:
if flame == -40: continue
img, rect = DATA.mag_images[self.frames[flame%5]]
rect.midbottom = (self.x + flame*8, self.y-math.sin(flame/2.0)*5.0+c*self.rise+((c+0.001)**(abs(self.rise)+1))*[1,-1][self.rise<0])
if self.check_collide(rect):
self.flame_entities[c] = -40
c += 1
if sum(self.flame_entities) == 8 * -40:
self.finished = True
def check_collide(self, crect):
for monster in self.MONSTERSTATE:
monsterrect = pygame.rect.Rect((0,0,monster.collision_dist*2,monster.collision_hdist*2))
monsterrect.center = monster.x, monster.y
if crect.colliderect(monsterrect):
damage = (self.caster.magic[0] * 3)/15.0
self.caster.combodamage += min(damage, monster.hp)
monster.react_to_magic(damage)
self.fvm = monster
self.fvd = damage
self.caster.combo += 1
return True
return False
class Summon(Spell):
def s_init(self):
self.caster.mbreaktime = 20
self.rays = []
self.alphamod = 0.0
def s_blit(self, surf, ALT_X, ALT_Y):
global DATA
alphamult = self.alphamod / 100.0
if alphamult > 0:
for width, phase, magnitude in self.rays:
rayrect = Rect(0, 0, width, 480)
variance = math.sin(phase) * magnitude
rayrect.midbottom = self.caster.x + variance, self.caster.y
raysurf = pygame.Surface(rayrect.size)
colour = (int(20 + magnitude * 2.5), 50 + width * 3, int(220 - phase * 10))
raysurf.fill(colour)
relalpha = max(0, min(255, 255 - (abs(variance)) * (255/100.0))) * 0.3
raysurf.set_alpha(alphamult * relalpha)
surf.blit(raysurf, rayrect.move(ALT_X, ALT_Y))
def stick(self):
ri = random.randint
if self.alphamod and self.caster.mbreaktime:
self.caster.animation = "Stopped"
self.caster.torso_animation = "Cast"
if self.ticker < 25:
# Creation of rays phase
if not self.ticker % 3:
self.rays.append([ri(5,35), ri(-30,30)/10.0, ri(5, 30)]) # Width, phase, magntd
self.alphamod = min(self.alphamod + 7.5, 100)
if self.ticker > 25:
self.alphamod -= 10
if self.alphamod < 0: self.alphamod = 0; self.finished = True
for r in range(len(self.rays)):
ray = self.rays[r]
self.rays[r][1] += ray[2]/300.0
class Burst(Spell):
def s_init(self):
global DATA
self.caster.mbreaktime = 30
def s_blit(self, surf, ALT_X, ALT_Y):
global DATA
self.mticker = -abs(self.ticker-15)+15
pic = DATA.mag_images["Burst.png"][0]
msurf = pygame.transform.scale(pic, (max(5, min(185, self.mticker**3))+15, max(5, min(185, self.mticker**3))+15))
msurf = pygame.transform.rotate(msurf, self.ticker**1.8)
rect = msurf.get_rect()
rect.center = (self.x + ALT_X, self.y + ALT_Y)
surf.blit(msurf, rect)
if self.ticker >= 30:
self.finished = True
def stick(self):
self.x, self.y = self.caster.x, self.caster.y - 40
if self.ticker%3: return
for monster in self.MONSTERSTATE:
dist = abs(monster.x - self.x) + abs(monster.y - self.y)
if dist > 110:
continue
monster.react_to_magic(0)
class Ice_1(Spell):
def s_init(self):
global DATA
self.affected = []
self.cant = self.caster.mp < 4
def s_blit(self, surf, ALT_X, ALT_Y):
global DATA
if not self.affected:
if self.ticker >= 0: self.finished = True
return
self.mticker = -abs(self.ticker-15)+15
msurf = pygame.transform.scale(DATA.mag_images["ice.png"][0], (max(5, min(125, self.mticker**2))+15, max(5, min(125, self.mticker**2))+15))
msurf = pygame.transform.rotate(msurf, self.ticker**1.7)
rect = msurf.get_rect()
for mon in self.affected:
rect.center = (mon.x + ALT_X, mon.y-40 + ALT_Y)
surf.blit(msurf, rect)
if self.ticker == 10:
dmg = int(random.randint(80,120)/100.0 * self.caster.magic[0] * 0.6)
self.caster.combodamage += min(dmg, mon.hp)
mon.react_to_magic(dmg)
self.fvm = mon
self.fvd = dmg
self.caster.combo += 1
if self.ticker >= 30:
self.finished = True
def stick(self):
if self.affected == []:
for monster in self.MONSTERSTATE:
xdist = abs(monster.x-self.caster.x)
if xdist < 300 and not monster.isdead:
if self.caster.mp[0] >= 4:
self.affected.append(monster)
self.caster.mp[0] -= 4
if len(self.affected):
self.SOUND = "Ice.ogg"
self.caster.animation = "Stopped"
self.caster.torso_animation = "Cast"
self.caster.frame = 0
self.caster.tframe = 0
self.caster.casting = True
self.caster.mbreaktime = 30
class Ice_2(Ice_1):
def s_init(self):
global DATA
self.affected = []
self.cant = self.caster.mp[0] < 8
def s_blit(self, surf, ALT_X, ALT_Y):
global DATA
if not self.affected:
if self.ticker >= 0: self.finished = True
return
self.mticker = -abs(self.ticker-15)+15
msurf = pygame.transform.scale(DATA.mag_images["ice2.png"][0], (max(5, min(125, self.mticker**2))+15, max(5, min(125, self.mticker**2))+15))
msurf = pygame.transform.rotate(msurf, self.ticker**1.7)
rect = msurf.get_rect()
for mon in self.affected:
rect.center = (mon.x + ALT_X, mon.y-40 + ALT_Y)
surf.blit(msurf, rect)
if self.ticker == 10:
dmg = int(random.randint(80,120)/100.0 * self.caster.magic[0] * 1.1)
self.caster.combodamage += min(dmg, mon.hp)
mon.react_to_magic(dmg)
self.fvm = mon
self.fvd = dmg
self.caster.combo += 1
if self.ticker >= 30:
self.finished = True
def stick(self):
if self.affected == []:
for monster in self.MONSTERSTATE:
xdist = abs(monster.x-self.caster.x)
if xdist < 300 and not monster.isdead:
if self.caster.mp[0] >= 8:
self.affected.append(monster)
self.caster.mp[0] -= 8
if len(self.affected):
# self.affected = reduce(lambda m1,m2:[m1,m2][abs(m2.x-self.caster.x)0,x>65 or x<0][self.unchdir]] for x in self.flame_entities]
if self.caster.up_held: self.rise -= 0.05
if self.caster.down_held: self.rise += 0.05
# Collision detections
c = 0
for flame in self.flame_entities:
if flame == -666: continue
img, rect = DATA.mag_images[self.frames[flame%5]]
rect.midbottom = (self.x + flame*4, self.y-math.sin(flame/2.0)*5.0+c*self.rise+((c+0.001)**(abs(self.rise)+1))*[1,-1][self.rise<0])
for y in range(-1,2):
if self.check_collide(rect.move(0, y*flame)):
self.flame_entities[c] = -666
c += 1
if sum(self.flame_entities) == 8 * -666:
self.finished = True
def check_collide(self, crect):
for monster in self.MONSTERSTATE:
monsterrect = pygame.rect.Rect((0,0,monster.collision_dist*2,monster.collision_hdist*2))
monsterrect.center = monster.x, monster.y
if crect.colliderect(monsterrect):
damage = (self.caster.magic[0] * 8)/60.0
self.caster.combodamage += min(monster.hp, damage)
monster.react_to_magic(damage)
self.fvm = monster
self.fvd = damage
self.caster.combo += 1
return True
return False
class Quake(Spell):
def s_init(self):
self.cost = 15
if self.caster.mp[0] < self.cost: self.finished = True; return
self.caster.mbreaktime = 26
self.caster.mp[0] -= self.cost
self.ticker = 0
self.px = 0
self.py = 0
def s_blit(self, surf, ALT_X, ALT_Y):
self.caster.quaking = True
def stick(self):
self.ticker += 1
hitlist = []
if not self.ticker%20:
for mon in self.MONSTERSTATE:
if mon.x > self.caster.x - 350 and mon.x < self.caster.x + 350:
if mon.affected["quake"]:
hitlist.append(mon)
for monster in hitlist:
damage = self.caster.magic[0] * 0.8
damage *= random.randint(75, 125)/100.0
self.caster.combodamage += min(damage, monster.hp)
monster.react_to_damage(int(damage))
self.caster.combo += 1
if self.ticker == 100:
self.finished = True
self.caster.quaking = False
class Implosion_1(Spell):
def s_init(self):
global DATA
self.affected = []
self.cant = self.caster.mp < 15
def s_blit(self, surf, ALT_X, ALT_Y):
global DATA
pic = DATA.mag_images["bubble.png"][0]
if not self.affected:
if self.ticker >= 0: self.finished = True
return
for mon in self.affected:
moncentre = (mon.x + ALT_X, mon.y-40 + ALT_Y)
eachang = (math.pi/4)
r = max(0, 300 - self.ticker*15)
turn = self.ticker / 5.0
sp = max(4, 20-self.ticker/2)
for x in range(8):
for c in range(10):
xp = math.cos(x * eachang + turn + (c * 0.15)*(-1**c)) * (r + c * sp)
yp = math.sin(x * eachang + turn + (c * 0.15)*(-1**c)) * (r + c * sp)
rect = pic.get_rect()
rect.center = moncentre
rect.move_ip(xp, yp)
surf.blit(pic, rect)
def stick(self):
if self.affected == []:
for monster in self.MONSTERSTATE:
xdist = abs(monster.x-self.caster.x)
if xdist < 400 and not monster.isdead:
if self.caster.mp[0] >= 15:
self.affected.append(monster)
self.affected.sort(lambda x, y: cmp(y.maxhp, x.maxhp))
if len(self.affected):
self.affected = self.affected[:1]
self.caster.mp[0] -= 15
self.SOUND = "Implosion.ogg"
self.caster.animation = "Stopped"
self.caster.torso_animation = "Cast"
self.caster.frame = 0
self.caster.tframe = 0
self.caster.casting = True
self.caster.mbreaktime = 25
for mon in self.affected:
if self.ticker >= 20 and not self.ticker%5:
dmg = int(random.randint(90,155)/100.0 * self.caster.magic[0] * 0.8)
self.caster.combodamage += min(dmg, mon.hp)
mon.react_to_magic(dmg)
self.fvm = mon
self.fvd = dmg
self.caster.combo += 1
if self.ticker >= 31:
self.finished = True
class Summon_Maea(Spell):
def s_init(self):
global DATA
self.cost = 80
if self.caster.mp[0] < self.cost: self.finished = True; return
self.caster.mbreaktime = 50
self.caster.mp[0] -= self.cost
self.dir = self.caster.direction
self.x = [640, -262][self.dir]
self.inertia = [-10, 10][self.dir]
self.bubbles = []
self.bombs = []
self.y = 50
self.inertia2 = 0
self.mouthpos = (130, 50)
def s_blit(self, surf, ALT_X, ALT_Y):
global DATA
darkness = pygame.Surface((640, 480))
if self.ticker < 120:
darkness.set_alpha(7 * min(30, self.ticker))
else:
darkness.set_alpha(max(0, 1050 - self.ticker*7))
surf.blit(darkness, (0,0))
if self.dir:
surf.blit(DATA.images["Summon1.png"][0], (self.x, self.y))
else:
surf.blit(pygame.transform.flip(DATA.images["Summon1.png"][0], True, False), (self.x, self.y))
for x, y, p in self.bombs:
bfs, bfr = DATA.images["bluefire.png"]
nbfs = pygame.transform.scale(bfs, (int(math.cos(-p/2) * 240), int(math.sin(p) * 250)))
nbfr = nbfs.get_rect()
nbfr.midbottom = (x, y + 5)
nbfr.move_ip(ALT_X, ALT_Y)
surf.blit(nbfs, nbfr)
for x, y, a in self.bubbles:
bs, br = DATA.mag_images["bubble.png"]
surf.blit(bs, br.move(self.mouthpos).move(x,y))
def stick(self):
self.x += self.inertia
if self.dir:
self.inertia -= 0.1
else:
self.inertia += 0.1
self.inertia2 += 0.01
self.y += self.inertia2
if self.x < -280 or self.x > 658: self.finished = True
if self.ticker <= 100 and not self.ticker%9:
if self.dir:
sp = int(self.caster.x - 300)
else:
sp = int(self.caster.x + 300)
cx = [sp - self.ticker * 8, sp + self.ticker * 8][self.dir]
self.bombs.append([cx, ground_at(self.LEVELSTATE, cx, True), 0])
# We want angle to swing like a pendulum between 45 and 135 degrees
degree_variance = math.sin(self.ticker/6.0) * 80
bdv = -degree_variance
degree = degree_variance + 90
angle = math.radians(degree)
self.bubbles.append([self.x, self.y, angle])
degree = bdv + 90
angle = math.radians(degree)
self.bubbles.append([self.x, self.y, angle])
for b in range(len(self.bubbles)):
self.bubbles[b][0] += math.cos(self.bubbles[b][2]) * 10
self.bubbles[b][1] += math.sin(self.bubbles[b][2]) * 10
for z in range(len(self.bombs)):
self.bombs[z][2] += 0.1
if self.bombs[z][2] > 3:
self.bombs[z] = None
continue
hitlist = []
if abs(self.bombs[z][2] - 1.1) < 0.0000001:
for monster in self.MONSTERSTATE:
if abs(monster.x - self.bombs[z][0]) < 100:
if monster.y > self.bombs[z][1] - 220:
hitlist.append(monster)
for monster in hitlist:
damage = self.caster.magic[0] * random.randint(8, 12) / 20.0
monster.react_to_damage(int(damage))
self.fvm = monster
self.fvd = damage
self.caster.Take_Damage(-1)
biggerhitlist = []
for monster in self.MONSTERSTATE:
if abs(monster.x - self.x) < 400:
if monster not in biggerhitlist:
biggerhitlist.append(monster)
for monster in biggerhitlist:
damage = 1
monster.react_to_damage(int(damage))
self.fvm = monster
self.fvd = damage
while None in self.bombs:
self.bombs.remove(None)
ardentryst-1.71/help.txt 0000644 0001750 0001750 00000010570 11232747326 015242 0 ustar vincent vincent Ardentryst
(C) 2007 - 2009
Jordan Trudgett
Help
FOR ANY QUESTIONS, do not hesitate to
email me, the creator, at
jordan_trudgett@hotmail.com
if they are not covered here!
Contents:
General game information ............ 1
Controlling the game ............ 2
Frequently asked questions ............ 3
Troubleshooting ............ 4
License ............ 5
===========================================
1. GENERAL GAME INFORMATION
===========================================
Ardentryst is an open-source free game written exclusively by Jordan
Trudgett. It works to combine elements of fighting, arcade, advent-
ure, RPG and sidescrolling games to give the game a very unique
genre. Its aim is to provide an enjoyable game to people of many ages
from young to old, and to appeal to many types of gamers.
Ardentryst works much like any other platform game in a bigger sense:
when you play the game, you move from level to level to play them, and
after each, you unlock the next. The goal is, generally, to finish all
the levels.
During each level, there are noticeable RPG and fantasy elements, like
the HP/MP/affliction statuses, to name a few. Many of these elements
have been carried over from traditional RPGs, like buying/selling
items, attack/defence/endurance/luck/level-based character development,
and of course, many different weapons and equipment to choose from.
The game also incorporates fighting-style combos in conjunction with
magic spells for advanced battles.
===========================================
2. CONTROLLING THE GAME
===========================================
In this game, most movement or selection changing will be done with
the keyboard: by default, the arrow keys. These controls are
redefineable in the options screen from the main menu.
Most choices are confirmed with Button 1, which is C on the keyboard,
by default. You can change this also.
Within a level, the buttons 1-8 operate on things in the level, and
button 9 pops up an in-game menu. Button 9 is Q by default. This
button will also work on any overview map, like when before starting a
level.
Whenever no controls are stated, it is generally safest to use C to
continue a textbox, or confirm an action, or continue in another way.
Up will make your character jump. Make sure to hold it down so you jump
the highest.
Left and right will make your character walk or move left and right.
W: Hold down to activate, then use Up/Down to move the camera
D: Start a spell
C: Main button/attack
Z: Activate (treasure, obelisks, levers, signs, NPCs)
===========================================
3. FREQUENTLY ASKED QUESTIONS
===========================================
Q. How many lines of code is the game so far?
A. 18000+ lines (July 09)
Q. When did you start?
A. 12 September, 2007
Q. Has the game always been called Ardentryst? What about Pyralis/Nyx?
A. No, it was first called Luna & Sol, the original names of the first
two characters, then it was renamed Luna because the game was going
to be changed to only having one character, then back to Luna &
Sol, then after a long time, Ardentryst. About a month or two after
that, the characters were renamed Pyralis and Nyx (after thought!)
Q. Will you sell this game?
A. No. The game will always be free and open-source.
Q. Do you make Ardentryst for money?
I develop Ardentryst as a hobby. I will accept donations though!
===========================================
4. TROUBLESHOOTING
===========================================
Q. The game is too slow.
A. As for an in-game fix, you can change the graphics intensity in the
options screen on the main menu. Usually, turning off unnecessary
effects like rain and some parallax layers can increase playability
dramatically.
Q. I found a bug, or I have a suggestion to make.
A. Please post in the Player Forums on the Ardentryst website
or e-mail me at jordan_trudgett@hotmail.com.
It might be worthwhile to include log.txt which can be
found in ~/.ardentryst/ or My Documents\.ardentryst\ (Windows).
===========================================
5. LICENSE
===========================================
See COPYING and COPYING.data files.
If you are unsure of what you can and can't
do with this software, or need to ask
permission to do something, email me at
jordan_trudgett@hotmail.com. Thanks!
The game media is covered under Creative
Commons - commercial use allowed
ardentryst-1.71/game.py 0000644 0001750 0001750 00000027704 11150727542 015040 0 ustar vincent vincent #------------------------------------------------------------------------
#
# This file is part of Ardentryst.
#
# Ardentryst is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ardentryst is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ardentryst. If not, see .
#
# Copyright 2007, 2008, 2009 Jordan Trudgett
#
#------------------------------------------------------------------------
import pygame, time, md5, random
from helpers import ge, myflip
from pygame.locals import *
from fade import *
import wordwrap
from math import radians, sin
#1st slide(bg,(txtlines),spch,alt.len,(prespeech,prescr,extrascr,endw),amb)
script = {
"End": [
"theme1.ogg",
("End.png",
("After Radkelu's evil power over Kiripan had been dispelled,", "Kiripan returned to the ground safely...", "and Ardentryst was saved from the clutches of despair!"),
None,
None,
(1, 25, 0, 2),
None
),
("End.png#",
("", "THE END"),
None,
None,
(3, 15, 0, 999),
None
),
("black.png",
("",""),
None,
1,
(0, 0, 0, 0),
"continue",
)
],
"Introduction": [
"Story.ogg",
("Intro_Kiripan_Village.png",
("When I was a child, I knew bright, blue days when",
"The heat was blaring, and the gulls were soaring."),
"VOI_Intro_1.ogg",
None,
(2, 1, 6, 1),
"AMB_Intro_1.ogg"
),
("Intro_Kiripan_Beach.png",
("I ... guess time escaped us....",
"We'd sit at the beach, watching the water come in, and leave;",
"Over and over."),
"VOI_Intro_2.ogg",
8,
(1, 0, 0, 0),
"AMB_Intro_2.ogg"
),
("Intro_Kiripan_Beach_Fade.png",
("", "Summer began to fade...."),
"VOI_Intro_3.ogg",
4,
(1, 0, 0, 1),
"AMB_Intro_3.ogg"
),
("black.png",
("I remember....",
"A huge tremor rumbled beneath us....",
"Chasms tore us apart."),
"VOI_Intro_4.ogg",
8,
(1, 0, 1, 0),
"continue"
),
("black.png#",
("Then suddenly,",
"Kiripan rose into the sky, high above the clouds...."),
"VOI_Intro_5.ogg",
5,
(1, 0, 0, 2),
"continue"
),
("Intro_Newspaper.png#",
("", "Day ... has turned to night."),
"VOI_Intro_6.ogg",
6,
(2, 0, 0, 3),
"AMB_Intro_6.ogg"
),
("black.png",
("",""),
None,
1,
(0, 0, 0, 0),
"continue",
)
],
}
def Wait_10_ms(t):
timebeen = (pygame.time.get_ticks() - t)
if timebeen < 10:
time.sleep((10 - timebeen) / 1000.0)
return
def r_wait(sec):
ft = pygame.time.get_ticks()
while pygame.time.get_ticks() < ft + sec*1000:
time.sleep(0.001)
for e in ge():
if e.type == KEYDOWN:
if e.key == K_ESCAPE or e.key == K_RETURN: return True
return False
class Game_Object:
def __init__(self):
self.savefilename = ""
self.character = "Nobody"
self.location = [1, 0] # [World, Level]
# since level is 0, we're on the world map
self.said_laggy = False
self.silver = 0
self.ENDSCENE = 0
self.startdate = ""
self.version = ""
self.world_tut = 0
self.game_tut = 0
self.ac_code = "".join([chr(97 + random.randint(0,25)) for x in range(4)]).upper()
self.playerobject = None
self.password = ""
self.Accessible = [
[1], # Worlds on world map that are accessible by default
[1], # Levels in semp. that are accessible by default
[1], # Levels in ent. that are accessible by default
[1, 2], # Levels in sno. that are accessible by default
]
self.scores = [
]
self.timegems = []
self.GID = md5.new(str(random.randint(0, 9999999)).zfill(7)+time.ctime()).hexdigest()
self.KIRI_HEIGHT = 1 # How high kiripan is levitated.
#1st slide(bg,(txtlines),spch,alt.len,(prespeech,prescr,extrascr,endw),amb)
self.hc = False
self.storyline = "When one of Ardentryst's Mages of Balance is struck by greed for power and becomes corrupt, the story of the small coastal town of Kiripan is changed forever... Nyx, the descendent and only daughter of the Entaryan Queen Amee, is an apprentice mage when she hears the news. Simultaneously, in the forest town Sempridge, Pyralis hears of the news from the local storyteller. When the evil mage Radkelu turned against the good mages, turning them to stone, he summoned a horde of creatures which came out of portals all throughout the land. They crawled the cities and the villagers fled. Rumour has it that Radkelu is hiding out in a cave atop the snowy mountain range Snodom. It is now up to the bravest souls of Entarya and Sempridge to rescue Kiripan from Radkelu's clutches..."
def text_intro(self, screen, data, fonts, soundbox):
soundbox.PlaySong("castle2.ogg", -1)
Quitsurfw = fonts[9].render("Hit ESC or RETURN to skip", 1, (255,255,255))
Quitrect = Quitsurfw.get_rect()
storysurfs = wordwrap.string_to_paragraph(self.storyline, fonts[22], 1, (220, 230, 255), 620)
h = 250
for s in storysurfs:
h += s.get_height()
bigsurf = pygame.Surface((640, h), SRCALPHA, 32)
ch = 0
bigsurf.blit(data.SSI["part1.png"][0], (61, 20))
for s in storysurfs:
r = s.get_rect()
r.midtop = (320, 215 + ch)
ch += r.height
bigsurf.blit(s, r)
# Now bigsurf is made.
height = 100
bigsurfheight = bigsurf.get_height()
tick = -bigsurfheight + height + 100
while tick < 500:
screen.blit(data.SSI["Kiripan_dark.png"][0], (0,0))
for ly in range(1, 850):
row = pygame.Surface((640, 1), SRCALPHA, 32)
# At ly = 1, the angle will be a little declining.
exte = ly / 20.0
inte = 90 - exte
dist = height * sin(radians(inte)) / sin(radians(exte))
imy = bigsurfheight - dist + tick
row.blit(bigsurf, (0, -imy))
w = ly * 1.5
row = pygame.transform.scale(row, (int(w/4.0)*4, 1))
rowr = row.get_rect()
rowr.midtop = (320, ly)
screen.blit(row, rowr)
tick += 1
Quitrect.bottomright = (635, 475)
screen.blit(Quitsurfw, Quitrect)
myflip()
if r_wait(0.01):return
def story_scene(self, scene, screen, d, f, s):
Scene_Info = script[scene]
Scene_Music = Scene_Info[0]
Old_Slide_Amb = None
Slide_Amb = None
Slide = 1
Showing = True
lh = 25
this_slide = pygame.Surface((640,480))
if Scene_Music:
s.PlaySong(Scene_Music, -1)
Quitsurfw = f[9].render("Hit ESC or RETURN to skip", 1, (255,255,255))
Quitsurfb = f[9].render("Hit ESC or RETURN to skip", 1, (0,0,0))
Quitrect = Quitsurfw.get_rect()
while Showing:
Amb_Cont = False
if Slide_Amb:
Old_Slide_Amb = Slide_Amb
Camera_X = 0
CUT = False
Slide_Info = Scene_Info[Slide]
Slide_Amb = Slide_Info[5]
if Slide_Amb == "continue": Slide_Amb = Old_Slide_Amb; Amb_Cont = True
if Slide_Amb and not Amb_Cont: s.PlaySound(Slide_Amb)
if Slide_Info[0][-1] == "#": CUT = True
if CUT:
Slide_Img, Slide_Rect = d.SSI[Slide_Info[0][:-1]]
else:
Slide_Img, Slide_Rect = d.SSI[Slide_Info[0]]
this_slide.blit(Slide_Img, (0,0))
if not CUT: fade_screens(screen, this_slide, 25)
else: screen.blit(this_slide, (0,0))
for x in range(-1,2):
for y in range(-1,2):
Quitrect.bottomright = (635+x, 475+y)
screen.blit(Quitsurfb, Quitrect)
Quitrect.bottomright = (635, 475)
screen.blit(Quitsurfw, Quitrect)
myflip()
Subtitles = Slide_Info[1]
Speech = Slide_Info[2]
Time_Wait = Slide_Info[4]
if Time_Wait[0]:
if r_wait(Time_Wait[0]):
break
if Old_Slide_Amb and not Amb_Cont:
s.FadeoutSoundSlow(Old_Slide_Amb)
if Speech: s.PlaySound(Speech); SlideLength = s.SoundLength(Speech)
SlideLength = 0.1
if Slide_Info[3]: SlideLength = Slide_Info[3]
if Subtitles:
for i in range(len(Subtitles)):
Sub_Img = f[12].render(Subtitles[i], 1, (0,0,0))
Sub_Rct = Sub_Img.get_rect()
Sub_Rct.centerx = 321
Sub_Rct.bottom = 475 - ((len(Subtitles)-i-1) * lh)
for x in range(-1, 2):
for y in range(-1, 2):
this_slide.blit(Sub_Img, Sub_Rct.move(x,y))
Sub_Img = f[12].render(Subtitles[i], 1, (255,255,255))
Sub_Rct = Sub_Img.get_rect()
Sub_Rct.centerx = 320
Sub_Rct.bottom = 475 - ((len(Subtitles)-i-1) * lh)
this_slide.blit(Sub_Img, Sub_Rct)
fade_screens(screen, this_slide, 10)
Extra_Space = Slide_Rect[2] - 640
Slide_Factor = Extra_Space / float((SlideLength-Time_Wait[1]+Time_Wait[2])*100)
Sliding = False
if Extra_Space:
Sliding = True
if not Sliding:
if r_wait(SlideLength):
break
if Time_Wait[1]:
if r_wait(Time_Wait[1]):
break
while Sliding:
t = pygame.time.get_ticks()
Camera_X += Slide_Factor
screen.blit(Slide_Img, (-Camera_X, 0))
if Subtitles:
for i in range(len(Subtitles)):
Sub_Img = f[12].render(Subtitles[i], 1, (0,0,0))
Sub_Rct = Sub_Img.get_rect()
Sub_Rct.centerx = 321
Sub_Rct.bottom = 475 - ((len(Subtitles)-i-1) * lh)
for x in range(-1,2):
for y in range(-1, 2):
screen.blit(Sub_Img, Sub_Rct.move(x,y))
Sub_Img = f[12].render(Subtitles[i], 1, (255,255,255))
Sub_Rct = Sub_Img.get_rect()
Sub_Rct.centerx = 320
Sub_Rct.bottom = 475 - ((len(Subtitles)-i-1) * lh)
screen.blit(Sub_Img, Sub_Rct)
myflip()
Wait_10_ms(t)
if r_wait(0.001): Showing = False
if Camera_X >= Extra_Space: Sliding = False
if not Showing: break
Slide += 1
if Slide == len(Scene_Info):
Showing = False
this_slide.blit(Slide_Img, (-Camera_X,0))
fade_screens(screen, this_slide, 10)
if not Showing: break
if Time_Wait[3]:
if r_wait(Time_Wait[3]):
break
fade_to_black(screen, 8)
s.FadeoutMusic(4000)
if Slide_Amb:
s.FadeoutSound(Slide_Amb)
if Speech:
s.FadeoutSound(Speech)
ardentryst-1.71/data.py 0000644 0001750 0001750 00000025512 11150727542 015033 0 ustar vincent vincent #------------------------------------------------------------------------
#
# This file is part of Ardentryst.
#
# Ardentryst is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ardentryst is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ardentryst. If not, see .
#
# Copyright 2007, 2008, 2009 Jordan Trudgett
#
#------------------------------------------------------------------------
import pygame, os, cPickle, sys
from item import *
from loading_screen import *
from helpers import logfile
def load_image(name, colorkey=None, blur = False, prefix = 'Data'):
fullname = os.path.join(prefix, name)
try:
image = pygame.image.load(fullname)
except pygame.error, message:
print 'Cannot load image:', fullname
raise SystemExit, message
if blur:
image.set_alpha(blur, RLEACCEL)
if colorkey is not None:
if colorkey is -1:
colorkey = image.get_at((0,0))
image.set_colorkey(colorkey, RLEACCEL)
image = image.convert_alpha()
return image, image.get_rect()
class Storage:
def __init__(self):
self.ItemAccumulation = None
self.imagefiles = [x for x in os.listdir(os.path.join(os.getcwd(), "Data")) if x.lower().endswith(".png")]
self.invitems = [x for x in os.listdir(os.path.join(os.getcwd(), "Data", "InvItems")) if x.lower().endswith(".png")]
self.eio = [x for x in os.listdir(os.path.join("Data","ObjectIcons")) if x.endswith(".png")]
self.images = {}
self.tilelist = [x for x in os.listdir(os.path.join("Data","tiles")) if x.endswith(".png")]
self.mag_image_sets = [
"fire1",
"burst",
"ice1",
"ice2",
"implosion1",
]
self.mag_sub_img_lists = []
for mag_image_set in self.mag_image_sets:
self.mag_sub_img_lists.append([mag_image_set] + [x for x in os.listdir(os.path.join("Data", "Magic", mag_image_set)) if x.lower().endswith(".png")])
self.mag_images = {}
self.pframefiles = [
# Player animation sprites
"Stopped1.png",
"Stopped2.png",
"Stopped3.png",
"Stopped4.png",
"Walking1.png",
"Walking2.png",
"Walking3.png",
"Walking4.png",
"Walking5.png",
"Walking6.png",
"Walking7.png",
"Walking8.png",
"Jumping1.png",
"Cast1.png",
"Attack1.png",
"Attack2.png",
"Attack3.png",
"Attack4.png"
]
self.pframes = {}
self.pframes2 = {}
# self.numbers = [str(x) + ".png" for x in range(10)] + \
# [str(x) + "b.png" for x in range(10)] + \
# [str(x) + "c.png" for x in range(10)]
self.numbers = [x for x in os.listdir(os.path.join("Data", "Numbers")) if x.endswith(".png")]
self.storysceneimages = [x for x in os.listdir(os.path.join("Data", "StorySceneImages")) if x.endswith(".png")]
self.SSI = {}
self.levelfiles = [[x for x in os.listdir(os.path.join("Levels")) if "." not in x]]
self.levels = {}
self.SONGS = [(x, x) for x in os.listdir(os.path.join("Music")) if x.endswith(".ogg") or x.endswith(".mp3")]
self.SOUNDS = [(x, x) for x in os.listdir(os.path.join("Sounds")) if x.endswith(".ogg")]
self.SOUNDS += [(os.path.join("PYR", x), x) for x in os.listdir(os.path.join("Sounds", "PYR")) if x.endswith(".ogg")]
self.SOUNDS += [(os.path.join("NYX", x), x) for x in os.listdir(os.path.join("Sounds", "NYX")) if x.endswith(".ogg")]
self.crawl_npc_files()
self.Itembox = ItemBox()
# <-- No more pre-loading filenames.
self.Monster_Data = {}
self.animlist = []
self.stage = 0
dofinal(self.makefinal())
self.showload = False
self.mimages = {}
self.crown_frames = []
def crawl_npc_files(self):
self.npc_image_data = []
self.npc_face_data = []
npclist = os.listdir(os.path.join("Data","NPCs","Frames"))
npcfacelist = os.listdir(os.path.join("Data", "NPCs", "Faces"))
for npc in npclist:
for frame in os.listdir(os.path.join("Data","NPCs","Frames",npc)):
if frame.lower().endswith(".png"):
self.npc_image_data.append(npc + "-" + frame)
for npcface in npcfacelist:
if npcface.endswith(".png"):
self.npc_face_data.append(npcface)
def dostage(self, filename, inc = 1):
if not self.showload: return
self.stage += inc
Update_Loading(self.stage, filename)
logfile("DATA: Successfully loaded: " + filename)
def makefinal(self):
lc = 0
for x in self.levelfiles:
for y in x:
lc += 2
self.ItemAccumulation = self.Itembox.Accumulate_Images()
return len(self.imagefiles) + len(self.tilelist) + 4*len(self.pframefiles)+\
len(self.ItemAccumulation)+ len(self.numbers) + \
len(self.eio) + len(self.storysceneimages) + len(self.invitems) + \
sum([len(x)-1 for x in self.mag_sub_img_lists]) + \
self.process_monster_file() + len(self.npc_image_data) + \
len(self.npc_face_data) + lc
def process_monster_file(self):
monfile = open(os.path.join("Base", "monsters.db"), "r")
data = monfile.readlines()
monname = None
mondata = {}
animlist = []
msoundlist = []
for line in data:
line = line.strip()
if not line or line[0] == "#": continue
if line[0] == "<":
monname = line[1:-1]
mondata[monname] = {"animations":[], "sounds":{}}
animlist.append([monname, "static.png"])
animlist.append([monname, "face.png"])
if ":" in line:
var = line[:line.index(":")]
val = line[line.index(":")+1:]
if var == "animation":
frames = int(val[val.index(";")+1:])
val = val[:val.index(";")]
for x in range(1, frames+1):
animlist.append([monname, val+str(x)+".png"])
mondata[monname]["animations"].append(val)
elif var == "sound":
sounds = int(val[val.index(";")+1:])
val = val[:val.index(";")]
mondata[monname]["sounds"][val] = []
for x in range(1, sounds+1):
msoundlist.append([monname, val+str(x)+".ogg"])
mondata[monname]["sounds"][val].append(val+str(x)+".ogg")
self.SOUNDS.append((os.path.join("MonsterSounds", monname.lower(),val+str(x)+".ogg"),monname+"_"+val+str(x)+".ogg"))
else:
mondata[monname][var] = val
self.Monster_Data = mondata
self.animlist = animlist
self.msoundlist = msoundlist
return len(animlist)
def precache_images(self):
for image in self.imagefiles:
self.images[image] = load_image(image)
self.dostage("Image: " + image)
for image in self.invitems:
self.images[image] = load_image(image, None, False, os.path.join("Data", "InvItems"))
self.dostage("Inventory image: " + image)
for imagedata in self.animlist:
mon, image = imagedata
if not self.mimages.has_key(mon): self.mimages[mon] = {}
self.mimages[mon][image] = load_image(image, None, False, os.path.join("Data", "MonsterFrames", mon.lower()))
self.dostage("Monster frame: " + mon + "/" + image)
for mag_image_set in self.mag_sub_img_lists:
magset = mag_image_set[0]
for image in mag_image_set[1:]:
self.mag_images[image] = load_image(image, None, False, os.path.join("Data", "Magic", magset))
self.dostage("Magic frame: " + image)
for image in self.storysceneimages:
self.SSI[image] = load_image(image, None, False, os.path.join("Data", "StorySceneImages"))
self.dostage("Story scene image: " + image)
for image in self.eio:
self.images[image] = load_image(image, None, False, os.path.join("Data", "ObjectIcons"))
self.dostage("Object icon: " + image)
for image in self.tilelist:
self.images[image] = load_image(image, None, False, os.path.join('Data', 'tiles'))
self.dostage("Tile image: " + image)
for image in self.numbers:
self.images[image] = load_image(image, None, False, os.path.join('Data', 'Numbers'))
self.dostage("Sprite font: " + image)
for image in self.pframefiles:
self.pframes[image] = [load_image("T_"+image, None, False, os.path.join('Data','Pyralis')),
load_image("L_"+image, None, False, os.path.join('Data','Pyralis'))]
self.pframes2[image] = [load_image("T_"+image, None, False, os.path.join('Data','Nyx')),
load_image("L_"+image, None, False, os.path.join('Data','Nyx'))]
self.dostage("Player animation: " + image, 4)
for npcdata in self.npc_image_data:
npcname, framefile = npcdata.split("-")
self.images["NPC-" + npcname + "-" + framefile] = load_image(
framefile, None, False, os.path.join("Data", "NPCs", "Frames", npcname))
self.dostage("NPC Frame: " + npcname + "/" + framefile)
for npcdata in self.npc_face_data:
self.images[npcdata] = load_image(
npcdata, None, False, os.path.join("Data", "NPCs", "Faces"))
self.dostage("NPC Face: " + npcdata)
for image in self.ItemAccumulation:
self.images[image] = load_image(image, None, False, os.path.join('Data', 'Items'))
self.dostage("Item overlay image: " + image)
def precache_levels(self):
for x in range(len(self.levelfiles)):
for levelfile in self.levelfiles[x]:
self.levels[levelfile] = cPickle.load(open(os.path.join("Levels", levelfile), "r"))
self.dostage(levelfile, 2)
ardentryst-1.71/icon2.png 0000644 0001750 0001750 00000021100 11222247760 015254 0 ustar vincent vincent PNG
IHDR @ @ iq pHYs tIME#5% tEXtComment Created with The GIMPd%n IDATxڅIeyݝȪbQl$1)YHI1,B'xO#xa؈Lb AfN80 #XA)+ q$[=H"Y$^.}*[/pQ]sQ1F~Bpzz%, q_BHH?+0Ɛ9eYRUUUQ%ZkɐRcZ]ױ;{O% {V}ߣf2ebwc@=eYcDJ!Zڶ9mf:ruuEZ犢`20_,X.,tCyRMP7
yQBg9NݬBrB9R
y)]qqqrD)Kbe9s
~_0r~CB[VWmG {\`_/HH6m4vQJ͔RccK)L&L1xǂ^0_5y1LKfqBu`zi[E5ŭ.?,Li1"dcB{L]dYk-Rʱr*`Wbćx$&1..RfLܺۺ[6ujE۶!ΩkBtim ĸ(RJ"!ĴQB!χ#9֛
ۺm]nm]Ӷ-!F`ZJ!w
hJ|ͱ5{?,ٔtt:c>(&1rv.Σ?#7{"sBH >hFjkڦi-v@mB\~g}{web>QV[ʣ!✦iRyKچ=!,GhvlyaPL&xP2-;c|:F "Z)m}W^y~CW~WX.(ih4^χL'GGG/X.EdҤǕvy8ąH0Y
!S $
!>0EQ*Jᴷ\rHw\;F眝Zf|e6s?/CoRU}.uI%j"OpΦ(lk!
SI,GiM#0Ը.$DpaE !??VTrJ)5|1'F8!9eӴ\^^2yY,<ܼy__Rol!ġYVVAaAbXB*Ȳm2@`KYBCާ"Z?VXP8B(K||v[^{W^$3>d:~PJrps! F1KFܼ>hAHCsDb!&M(E ?Зw]C α˯0Ψʊ,ygxt$|<zezn8譥:ڶ6@*(
5p@B+H )D
9Lr*sΡa>j2I2"
6__EihcM<7%,"m=3,K(b|rrbI5%Jp&-N!RmPR
E]#Y|JAN֚rJ)=HE S^'>"8Y!=eQ2LR (Y,3X,Z6-[V
ZmV $Y
:Į&HR`aDa_MI
egQ@[wm!p~qN۴pbaCe6Cuͷmܺ4dY"bjpt|drp[v-[i3L #q4ġJ! Eö"$/J:&I*TQ[yHq|f*BSHI_pyu5{, E <(˒:rJXT)y9~IRw\HPB"d$D<B3
RՊ+Vy1y1CKQ$zTE%ZH\^{5~7JzdBUCl:aS7dyN^dy2a̮f3fFe!2E!%bHa}(! Cʇ蜊nL9ی]. e}6u\&ՔzЊ\"n]їΒe9wt9PReV\1YF^,tݘFkT:hVB+g!$.C#ҠvH*ҚiHi7Im ny7/'CQ"/nRqM]OQ AUM6,ulvێ8#$۔)dRMD0|/%J*1 $y3IE}8 G)MP&iZe[Պ]I,+ɋ-
|f$kwt[oPfU5{zVAD qD=ET
UUBj*ݬ6(MfBQߟ͝wߥYٮW4nmw@aU%)IUQ%Ee,Ogb%z3=Y}iA5:Em۰(H|,'-m %(*ڮGjs?1y!DB1D,JV,Rpg-M)b NP9F
0T̈́ͺ#v/Gg-TDѣDy"@ bt1CKi1۶oT}G3` ,y^pxx@u;9%@44-ZkLo稢*r2J1u>~nU%'RCYL$Ș(A=yzh 1CDz
!PG뿪D{auq]l7UɍיL&\Chۆo~[hc
d,0@4./9'L32Rô*Ω(E-l'@alQum6W~ȥ<6 "rz