# 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 MorkulAIController(npc.AIController):
  aggressivity  = 0.8
  dodge         = 0.03
  
  def __init__(self, mobile):
    npc.AIController.__init__(self, mobile)
    
  def attack(self, enemy):
    h = random.random()
    if   h < 0.75: yield self.attack_basic(enemy)
    else:         yield self.attack_jump (enemy)
    #if   h < 0.7: yield self.attack_basic(enemy)
    #elif h < 0.9: yield self.attack_jump (enemy)
    #else:         yield self.attack_side (enemy)
    
    
class Morkul(npc.Monster):
  Controller = MorkulAIController
  
  race           = "morkul"
  die_duration1  = 114
  die_duration2  = 102
  move_speed     =  0.8
  couic_sound    = "couic_morkul.wav"
  die_sound      = "grogne2.wav"
  
  def __init__(self):
    npc.Monster.__init__(self)
    
    self.perso = soya.Cal3dVolume(self, soya.Cal3dShape.get("beuglaz"), ["perso"])
    #self.perso.animate_blend_cycle("attente")
    
    #self.perso.set_shape(soya.Cal3dShape.get("beuglaz"), ["perso"])
    
    self.fighting   = 1.0
    self.resistance = 0.4
    
    self.add_item(balazar.item.Knife(), 0)
    if random.random() < 0.1: self.add_item(random.choice(balazar.item.SMALL_TREASURE)(), 0)
    self.auto_equip_items()
    
    self.relations["morkul"] =  1.0
    self.relations[None    ] = -0.5
    
  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 = "combat0"
    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))
    elif action.duration < 10: pass
    else:
      max_dz = 0.4 - math.sqrt((self.x - state.x) ** 2 + (self.z - state.z) ** 2)
      state.shift(0.0, 0.0, -min(0.2, max_dz))
    action.duration += 1
    if action.duration > 27: self.striking = 0; self.current_action = None
    

class MorkulChief(Morkul):
  move_speed =  0.7
  
  def __init__(self):
    npc.Monster.__init__(self)
    
    self.perso = soya.Cal3dVolume(self, soya.Cal3dShape.get("chef_morkul"), ["perso"])
    #self.perso.animate_blend_cycle("attente")
    
    #self.perso.set_shape(soya.Cal3dShape.get("chef_morkul"), ["perso"])
    
    self.fighting   = 1.5
    self.resistance = 1.0
    
    self.relations["morkul"] =  1.0
    self.relations[None    ] = -0.5
    
    self.add_item(balazar.item.Axe(), 0)
    if random.random() < 0.2: self.add_item(random.choice(balazar.item.SMALL_TREASURE)(), 0)
    self.auto_equip_items()
    

class MorkulChiefWithScepter(MorkulChief):
  def __init__(self):
    MorkulChief.__init__(self)
    
    self.add_item(balazar.item.PomponScepter(), 0)
    self.auto_equip_items()
    
