# Balazar # Copyright (C) 2004-2005 Jean-Baptiste LAMY # # This program 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 2 of the License, or # (at your option) any later version. # # This program 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 this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import random import soya, tofu from soya import Point, Vector from balazar.controller import StackController, Goto, GotoXZ, Gotoward, LookAt, GrabItem, Fly, Wait, Wander from balazar.character import * from balazar.character import _P, _V import balazar.globdef as globdef import balazar.base as base import balazar.sound import balazar.npc as npc class AIController(npc.AIController): aggressivity = 0.4 dodge = 0.9 def __init__(self, mobile): npc.AIController.__init__(self, mobile) def attack(self, enemy): h = random.random() if h < 0.40: yield self.attack_basic (enemy) elif h < 0.50: yield self.attack_jump (enemy) elif h < 0.80: yield self.attack_jump_over (enemy) elif h < 0.95: yield self.attack_side (enemy) else: yield self.attack_back (enemy) def do_nothing(self): if random.random() < 0.06: yield Wait (self.mobile, 200) else: yield Wander(self.mobile, 200) class FixedAIController(AIController): def do_nothing(self): yield Wait(self.mobile, 400) def interest(self, o, d = None): if isinstance(o, Item): return 0.0 return AIController.interest(self, o, d) class Echassian(npc.Monster, base.Discutable): Controller = AIController race = "echassian" die_duration1 = 114 die_duration2 = 155 move_speed = 1.05 couic_sound = "couic_morkul.wav" die_sound = "grogne2.wav" def __init__(self): npc.Monster.__init__(self) self.perso = soya.Cal3dVolume(self, soya.Cal3dShape.get("echassien2"), ["perso"]) self.fighting = 1.2 self.resistance = 1.5 if random.random() < 0.3: self.add_item(balazar.item.Knife(), 0) else: self.add_item(balazar.item.Sword(), 0) if random.random() < 0.3: self.add_item(random.choice(balazar.item.SMALL_TREASURE)(), 0) self.auto_equip_items() self.relations["Echassian"] = 1.0 def discussion_action___echassien_0__0_1_0(self, hero): self.set_relation(hero, -1.0) def start_discussion(self, hero): if not self.is_enemy(hero): from balazar.game_interface import AutoDiscussion AutoDiscussion(hero, self, u"", u"__echassien_0__0").activate(0) def strike_left(self, target): yield FightAction(ACTION_FIGHT_LEFT, target) yield Action(ACTION_WAIT) for i in range(26): yield None def strike_right(self, target): yield FightAction(ACTION_FIGHT_RIGHT, target) yield Action(ACTION_WAIT) for i in range(26): yield None def strike_charge(self, target): yield FightAction(ACTION_FIGHT_CHARGE, target) yield Action(ACTION_WAIT) for i in range(26): yield None def strike_sagittal(self, target): yield FightAction(ACTION_FIGHT_SAGITTAL, target) yield Action(ACTION_WAIT) for i in range(29): yield None def do_action_31(self, action, state): # ACTION_FIGHT_LEFT state.animation = "combat1" target = (action.target_uid and tofu.Unique.hasuid(action.target_uid) and tofu.Unique.getbyuid(action.target_uid)) or None if target: _P.clone(target) _P.convert_to(self) if _P.x > 0.1: state.rotate_lateral(-2.0) else: state.rotate_lateral(4.0) else: state.rotate_lateral(4.0) if action.duration == 0: self.kill_rays = self.weapon.kill_rays elif action.duration == 10: self.striking = 1; self.doer.action_done(SoundState(self, "strike2.wav", 4.0)) action.duration += 1 if action.duration > 27: self.striking = 0; self.current_action = None def do_action_32(self, action, state): # ACTION_FIGHT_RIGHT state.animation = "combat0" target = (action.target_uid and tofu.Unique.hasuid(action.target_uid) and tofu.Unique.getbyuid(action.target_uid)) or None if target: _P.clone(target) _P.convert_to(self) if _P.x > -0.1: state.rotate_lateral(-4.0) else: state.rotate_lateral(2.0) else: state.rotate_lateral(-4.0) if action.duration == 0: self.kill_rays = self.weapon.kill_rays elif action.duration == 10: self.striking = 1; self.doer.action_done(SoundState(self, "strike2.wav", 4.0)) action.duration += 1 if action.duration > 27: self.striking = 0; self.current_action = None def do_action_33(self, action, state): # ACTION_FIGHT_SAGITTAL state.animation = "combat3" target = (action.target_uid and tofu.Unique.hasuid(action.target_uid) and tofu.Unique.getbyuid(action.target_uid)) or None if target: self.strike_rot(target, state) if action.duration == 0: self.kill_rays = self.weapon.kill_rays elif action.duration == 10: self.striking = 1; self.doer.action_done(SoundState(self, "strike3.wav", 4.0)) action.duration += 1 if action.duration > 30: self.striking = 0; self.current_action = None def do_action_34(self, action, state): # ACTION_FIGHT_CHARGE state.animation = "combat2" target = (action.target_uid and tofu.Unique.hasuid(action.target_uid) and tofu.Unique.getbyuid(action.target_uid)) or None if target: self.strike_rot(target, state) if action.duration == 10: self.striking = 1; self.doer.action_done(SoundState(self, "strike2.wav", 2.0)) max_dz = 0.4 - math.sqrt((self.x - state.x) ** 2 + (self.z - state.z) ** 2) if 10 < action.duration < 20: state.shift(0.0, 0.0, -min(0.4 , max_dz)) else : state.shift(0.0, 0.0, -min(0.15, max_dz)) action.duration += 1 if action.duration > 30: self.striking = 0; self.current_action = None class EchassianMiller(Echassian): Controller = FixedAIController discussion_radius = 2.5 def discussion_is_valid___echassien_meunier__0_1_0(self, hero): return hero.get_item(balazar.item.MushroomFood) and not hero.level.wind def discussion_is_valid___echassien_meunier__0_1_1(self, hero): return hero.get_item(balazar.item.MushroomFood) and hero.level.wind def discussion_action___echassien_meunier__0_1_1(self, hero): item = hero.get_item(balazar.item.MushroomFood) if item: hero.doer.do_action(ItemAction(ACTION_DROP_ITEM, item)) def discussion_is_valid___echassien_meunier__0_2_0(self, hero): return not hero.level.wind def start_discussion(self, hero): if not self.is_enemy(hero): from balazar.game_interface import AutoDiscussion AutoDiscussion(hero, self, u"", u"__echassien_meunier__0").activate(0) class EchassianCartograph(Echassian): Controller = FixedAIController discussion_radius = 3.0 def __init__(self): Echassian.__init__(self) self.perso.set_shape(soya.Cal3dShape.get("echassien2@vert"), ["perso"]) self.add_item(balazar.item.Map("foret_pompon"), 0) def discussion_action___echassien_cartographe__0_1_0(self, hero): import balazar.trap self.level.get_by_class(balazar.trap.IndicatorPlatForm).rotate_toward(1.0, 0.0) def discussion_action___echassien_cartographe__0_2_0(self, hero): import balazar.trap self.level.get_by_class(balazar.trap.IndicatorPlatForm).rotate_toward(0.0, -1.0) def start_discussion(self, hero): if not self.is_enemy(hero): from balazar.game_interface import AutoDiscussion AutoDiscussion(hero, self, u"", u"__echassien_cartographe__0").activate(0)