/**
  * Check of a character can move from one area to the other
  *
  * @param int $area_id_from the ID of the current area
  * @param int $area_id_to the ID of the area where the character wanna go
  * @param int @character_id the current character ID
  * @return boolean whenever the character can move or not
  */
 function canMove($area_id_from = null, $area_id_to = null, $character_id = null)
 {
     $this->contain();
     $areaFrom = $this->find('first', array('conditions' => array('Area.id' => $area_id_from)));
     $areaTo = $this->find('first', array('conditions' => array('Area.id' => $area_id_to)));
     if ($areaFrom['Area']['travel_to_quest_id'] != 0) {
         App::import('Model', 'CharactersQuest');
         $CharactersQuest = new CharactersQuest();
         $someQuest = $CharactersQuest->find('first', array('conditions' => array('CharactersQuest.quest_id' => $areaFrom['Area']['travel_to_quest_id'], 'CharactersQuest.character_id' => $character_id, 'CharactersQuest.completed' => 'finished')));
         if (empty($someQuest)) {
             return false;
         }
     }
     return true;
 }
 function game_abandon($id = null)
 {
     App::import('Model', 'CharactersQuest');
     $CharactersQuest = new CharactersQuest();
     $CharactersQuest->deleteAll(array('quest_id' => $id, 'character_id' => $this->Session->read('Game.Character.id'), 'completed' => array('yes', 'no')));
     $this->redirect('/game/quests');
 }
 /**
  * Get the avaible options of npc/character conversation
  * @return array
  */
 function getOptions($npc_id = null, $character_id = null)
 {
     if (!isset($npc_id) || empty($npc_id) || !isset($character_id) || empty($character_id)) {
         return array();
     }
     $this->bindModel(array('hasMany' => array('Log')));
     $this->Log->bindModel(array('belongsTo' => array('Conversation')));
     $last_log = $this->Log->find('first', array('conditions' => array('Log.npc_id' => $npc_id, 'Log.character_id' => $character_id), 'order' => 'Log.created DESC'));
     if (!empty($last_log)) {
         // Get the conversation
         $conditions = array();
         if ($last_log['Conversation']['conversation_goto'] != 0) {
             $conditions['Conversation.parent_id'] = $last_log['Conversation']['conversation_goto'];
         } else {
             $conditions['Conversation.parent_id'] = $last_log['Conversation']['id'];
         }
         $this->unbindModel(array('hasMany' => array('Log')));
         $available_conversations = $this->find('all', array('conditions' => $conditions));
         // In het geval dat er we naar een conversation moeten gaan, pakken we daar ook de laat gesproken antwoord van
         if ($last_log['Conversation']['conversation_goto'] != 0) {
             $this->unbindModel(array('hasMany' => array('Log')));
             $last_log = $this->find('first', array('conditions' => array('Conversation.id' => $last_log['Conversation']['conversation_goto'])));
         }
     } else {
         $this->unbindModel(array('hasMany' => array('Log')));
         $last_log = $this->find('first', array('conditions' => array('Conversation.npc_id' => $npc_id, 'Conversation.parent_id' => '0')));
         $this->unbindModel(array('hasMany' => array('Log')));
         $available_conversations = $this->find('all', array('conditions' => array('Conversation.parent_id' => $last_log['Conversation']['id'])));
     }
     // Voor sommige quests moeten bepaalde quest behaald zijn (of mee bezig zijn). Kijken of dat bij deze quests het geval is...
     App::import('Model', 'ConversationsQuest');
     $ConversationsQuest = new ConversationsQuest();
     App::import('Model', 'CharactersQuest');
     $CharactersQuest = new CharactersQuest();
     /*
     		$ConversationsQuest->bindModel(array('hasOne' =>
     			array(
     				'CharactersQuest' => array(
     					#'foreignKey' => false,
     					#'foreignKey' => 'ConversationsQuest.quest_id = CharactersQuest.quest_id',
     					'conditions' => array(
     						'CharactersQuest.character_id' => $character_id
     					)
     				)
     			)
     		));
     */
     $conversations_ids = array();
     foreach ($available_conversations as $index => $conversation) {
         if ($conversation['Conversation']['quest_id'] != '0') {
             // Er moet een quest zijn voor deze conversation
             $someQuest = $CharactersQuest->find('first', array('conditions' => array('CharactersQuest.quest_id' => $conversation['Conversation']['quest_id'], 'CharactersQuest.character_id' => $character_id, 'CharactersQuest.completed' => 'finished')));
             if (empty($someQuest)) {
                 unset($available_conversations[$index]);
             }
         }
         // Let op! Dit zijn acties...
         if (!empty($conversation['Quest'])) {
             // Kijken of er een quest completed moet zijn...
             foreach ($conversation['Quest'] as $ActionsQuest) {
                 // @TODO. Check it in Quest->canView()
                 if ($ActionsQuest['ActionsConversation']['type'] == 'completequest') {
                     // Dan moet deze quest ook wel klaar zijn om in te leveren zijn...
                     $someQuest = $CharactersQuest->find('first', array('conditions' => array('CharactersQuest.quest_id' => $ActionsQuest['ActionsConversation']['target_id'], 'CharactersQuest.character_id' => $character_id, 'CharactersQuest.completed' => 'yes')));
                     if (empty($someQuest) && isset($available_conversations[$index])) {
                         unset($available_conversations[$index]);
                     }
                 } elseif ($ActionsQuest['ActionsConversation']['type'] == 'getquest') {
                     // Ervoor zorgen dat je niet 2x dezelfde quest kan krijgen...
                     // Dan moet deze quest ook wel klaar zijn om in te leveren zijn...
                     // @TODO kijken of je hier niet een quest hebt wat 'repeatable' is...
                     $someQuest = $CharactersQuest->find('first', array('conditions' => array('CharactersQuest.quest_id' => $ActionsQuest['ActionsConversation']['target_id'], 'CharactersQuest.character_id' => $character_id)));
                     if (!empty($someQuest) && isset($available_conversations[$index])) {
                         unset($available_conversations[$index]);
                     }
                 }
             }
         }
         if (isset($available_conversations[$index])) {
             $conversations_ids[$conversation['Conversation']['id']] = $conversation['Conversation']['id'];
         }
     }
     $ConversationsQuests = $ConversationsQuest->find('all', array('conditions' => array('ConversationsQuest.conversation_id' => $conversations_ids)));
     foreach ($ConversationsQuests as $ConversationsQuest) {
         // Controleren of de character deze conversation wel mag zien...
         // Compleet en moet deze compleet zijn?
         // De bijhorende quest opvragen...
         $CharactersQuestData = $CharactersQuest->find('first', array('conditions' => array('CharactersQuest.quest_id' => $ConversationsQuest['ConversationsQuest']['quest_id'], 'CharactersQuest.character_id' => $character_id)));
         if ($ConversationsQuest['ConversationsQuest']['completed'] == 'yes') {
             // De conversation mag alleen zichtbaar zijn als de gebruiker deze ook compleet heeft.
             if ($CharactersQuestData['CharactersQuest']['completed'] != 'yes') {
                 unset($conversations_ids[$ConversationsQuest['ConversationsQuest']['conversation_id']]);
             }
         } elseif ($ConversationsQuest['ConversationsQuest']['completed'] == 'no') {
             // De conversation mag alleen zichtbaar zijn als de gebruiker deze niet compleet heeft.
             if ($CharactersQuestData['CharactersQuest']['completed'] != 'no') {
                 unset($conversations_ids[$ConversationsQuest['ConversationsQuest']['conversation_id']]);
             }
         } elseif ($ConversationsQuest['ConversationsQuest']['completed'] == 'finished') {
             // De conversation mag alleen zichtbaar zijn als de gebruiker deze niet compleet heeft.
             if ($CharactersQuestData['CharactersQuest']['completed'] != 'finished') {
                 unset($conversations_ids[$ConversationsQuest['ConversationsQuest']['conversation_id']]);
             }
         } elseif ($ConversationsQuest['ConversationsQuest']['completed'] == 'all') {
             // De conversation mag alleen zichtbaar zijn als de gebruiker deze niet compleet heeft.
             if ($CharactersQuestData['CharactersQuest']['completed'] != '') {
                 // Bij geen resultaat is de gebruiker niet aan deze quest bezig
                 unset($conversations_ids[$ConversationsQuest['ConversationsQuest']['conversation_id']]);
             }
         }
     }
     if (!empty($conversations_ids)) {
         $available = $this->find('all', array('conditions' => array('Conversation.id' => $conversations_ids)));
     } else {
         $available = array();
     }
     return array('available' => $available, 'last_log' => $last_log);
 }
 /**
  * Check if a character can loot a item
  *
  * There are a several conditions before an item can be looted.
  * If the field `Item.unique` is greater then 0 the item may not be looted if
  * the character has already the number of `unique` in it's bags. In case of
  * the field `AreasObstaclesItem.max_drop` is greater than 0 the item may not
  * be looted again. If `AreasObstaclesItem.player_only` this last conditions is
  * per Character and not per game. So it is possible to loot an very rarely item
  * witch can be looted X times in a game.
  * There is also a field called `AreasObstaclesItem.spawn_time`. This is the time
  * in seconds between the item can looted. If `AreasObstaclesItem.player_only` is
  * set to 1 this only counts for the player.
  * If the character doesn't have enough space in it's back the item cannot be
  * loaded aswell.
  * An item can only be looted if the character is at the same location of the item.
  * Some items can only be looted if the character is on a quest (and not completed).
  *
  * @param int $character_id the current character ID
  * @param int $areas_obstacles_item_id the ID of the Area_Obstacle_Item @see `areas_obstacles_items`
  * @param int $area_id the current area of the character
  * @return boolean whenever the character can loot or not
  */
 function canLoot($areas_obstacles_item_id = null, $character_id = null, $area_id = null)
 {
     if (!isset($character_id) || !isset($areas_obstacles_item_id)) {
         return false;
     }
     $conditions = array();
     $conditions['Drop.character_id'] = $character_id;
     App::import('Model', 'AreasObstaclesItem');
     $AreasObstaclesItem = new AreasObstaclesItem();
     $AreasObstaclesItem->contain(array('AreasObstacle'));
     $drop = $AreasObstaclesItem->find('first', array('conditions' => array('AreasObstaclesItem.id' => $areas_obstacles_item_id)));
     if ($drop['AreasObstacle']['area_id'] != $area_id) {
         return false;
     }
     if ($drop['AreasObstaclesItem']['quest_id'] != 0) {
         App::import('Model', 'CharactersQuest');
         $CharactersQuest = new CharactersQuest();
         $hasQuest = $CharactersQuest->find('first', array('conditions' => array('CharactersQuest.character_id' => $character_id, 'CharactersQuest.quest_id' => $drop['AreasObstaclesItem']['quest_id'], 'CharactersQuest.completed' => 'no')));
         if (empty($hasQuest)) {
             return false;
         }
     }
     if (isset($drop['AreasObstaclesItem']['item_id'])) {
         $conditions['Drop.item_id'] = $drop['AreasObstaclesItem']['item_id'];
     }
     $allDrops = $this->find('count', array('conditions' => array('Drop.character_id' => $character_id, 'Drop.item_id' => $drop['AreasObstaclesItem']['item_id'], 'Drop.areas_obstacle_item_id' => $drop['AreasObstaclesItem']['id'])));
     App::import('Model', 'Inventory');
     $Inventory = new Inventory();
     $Inventory->contain();
     $hasAmount = $Inventory->find('count', array('conditions' => array('Inventory.character_id' => $character_id, 'Inventory.item_id' => $drop['AreasObstaclesItem']['item_id'])));
     if (isset($drop['AreasObstaclesItem']['max_drop']) && $drop['AreasObstaclesItem']['max_drop'] > 0) {
         if ($allDrops >= $drop['AreasObstaclesItem']['max_drop'] && $hasAmount >= $drop['AreasObstaclesItem']['max_drop']) {
             return false;
         }
     }
     if (isset($drop['AreasObstaclesItem']['spawn_time']) && $drop['AreasObstaclesItem']['spawn_time'] > 0) {
         $conditions['Drop.created >'] = date('Y-m-d H:i:s', strtotime("-" . $drop['AreasObstaclesItem']['spawn_time'] . " seconds"));
     }
     $conditions['Drop.areas_obstacle_item_id'] = $drop['AreasObstaclesItem']['id'];
     $someDrops = $this->find('first', array('conditions' => $conditions));
     if (!$this->hasFreeSpace($character_id, $drop['AreasObstaclesItem']['item_id'])) {
         return false;
     }
     if (empty($someDrops)) {
         return true;
     } else {
         if ($hasAmount < $drop['AreasObstaclesItem']['max_drop']) {
             return true;
         } else {
             return false;
         }
     }
 }
 /**
  * Updates a Quest for a Character. If the Quest is completed and turned in
  * the Character may receive some Quest rewards.
  *
  * @param int $quest The ID of the quest
  * @param int $character_id The ID of the Character
  * @param boolean $turnIn Whenever this quest is turning in
  */
 function update($quest_id = null, $character_id = null, $turnIn = false)
 {
     App::import('Model', 'CharactersQuest');
     $CharactersQuest = new CharactersQuest();
     $conditions = array();
     $conditions['CharactersQuest.completed !='] = 'finished';
     if (isset($quest_id)) {
         $conditions['CharactersQuest.quest_id'] = $quest_id;
     }
     if (isset($character_id)) {
         $conditions['CharactersQuest.character_id'] = $character_id;
     }
     $quests = $CharactersQuest->find('all', array('conditions' => array($conditions)));
     if (!empty($quests)) {
         // Inventory, Kill maybe needed
         App::import('Model', 'Inventory');
         $Inventory = new Inventory();
         App::import('Model', 'Kill');
         $Kill = new Kill();
         $charactersQuestsData = array();
         $i = 0;
         foreach ($quests as $quest) {
             $charactersQuestsData[$i]['id'] = $quest['CharactersQuest']['id'];
             // Get the needed things (items, object, whatever) here
             $itemsNeeded = $this->ItemsQuest->find('list', array('conditions' => array('ItemsQuest.quest_id' => $quest['CharactersQuest']['quest_id'], 'ItemsQuest.type' => 'needed'), 'fields' => array('ItemsQuest.item_id', 'ItemsQuest.amount')));
             $mobsNeeded = $this->MobsQuest->find('list', array('conditions' => array('MobsQuest.quest_id' => $quest['CharactersQuest']['quest_id']), 'fields' => array('MobsQuest.mob_id', 'MobsQuest.amount')));
             $itemsRewards = $this->ItemsQuest->find('list', array('conditions' => array('ItemsQuest.quest_id' => $quest['CharactersQuest']['quest_id'], 'ItemsQuest.type' => 'reward'), 'fields' => array('ItemsQuest.item_id', 'ItemsQuest.amount')));
             $statsRewards = $this->QuestsStat->find('list', array('conditions' => array('QuestsStat.quest_id' => $quest['CharactersQuest']['quest_id']), 'fields' => array('QuestsStat.stat_id', 'QuestsStat.amount')));
             $completed = '';
             if (empty($itemsNeeded) && empty($mobsNeeded)) {
                 // Geen items nodig.. Omdat er op het moment niks anders is om te controleren updaten we deze quest...
                 if ($turnIn == true && isset($character_id) && isset($quest_id)) {
                     $charactersQuestsData[$i]['completed'] = 'finished';
                 } else {
                     $charactersQuestsData[$i]['completed'] = 'yes';
                 }
             } else {
                 $completed = 'yes';
                 // Default it's completed.
                 $itemList = array();
                 $mobList = array();
                 foreach ($itemsNeeded as $item_id => $amount) {
                     $itemList[] = $item_id;
                 }
                 foreach ($mobsNeeded as $mob_id => $amount) {
                     $mobList[] = $mob_id;
                 }
                 // Er zijn items nodig voor deze quest..  Kijken of deze al gehaald zijn...
                 // ItemsNeeded: item_id => aantal_needed
                 $characterInventories = $Inventory->find('all', array('conditions' => array('Inventory.character_id' => $quest['CharactersQuest']['character_id'], 'Inventory.item_id' => $itemList), 'fields' => array('Inventory.item_id', 'COUNT(Inventory.item_id) as amount'), 'group' => array('Inventory.item_id')));
                 // Er zijn mobs nodig voor deze quest. Kijken of ze gekilled zijn NADAT de quest is geaccepteerd...
                 $characterKills = $Kill->find('all', array('conditions' => array('Kill.character_id' => $quest['CharactersQuest']['character_id'], 'Kill.mob_id' => $mobList, 'Kill.type' => 'mob', 'Kill.created >=' => $quest['CharactersQuest']['created']), 'fields' => array('Kill.mob_id', 'COUNT(Kill.target_id) as amount'), 'group' => array('Kill.target_id')));
                 // We hebben een lijst met items wat nodig is..
                 // En dit wordt een lijst met wat we hebben...
                 $itemsHave = array();
                 foreach ($characterInventories as $characterInventory) {
                     $itemsHave[$characterInventory['Inventory']['item_id']] = $characterInventory[0]['amount'];
                 }
                 // Opslaan yes/no of de quest compleet is...
                 foreach ($itemsNeeded as $item_id => $amount) {
                     if (!isset($itemsHave[$item_id]) || isset($itemsHave[$item_id]) && $itemsHave[$item_id] < $itemsNeeded[$item_id]) {
                         $completed = 'no';
                     }
                 }
                 // We hebben nu een lijst met mobs die nodig zijn, en een lijst met kills
                 $mobsHave = array();
                 foreach ($characterKills as $characterKill) {
                     $mobsHave[$characterKill['Kill']['mob_id']] = $characterKill[0]['amount'];
                 }
                 // Opslaan yes/no of de quest compleet is...
                 foreach ($mobsNeeded as $mob_id => $amount) {
                     if (!isset($mobsHave[$mob_id]) || isset($mobsHave[$mob_id]) && $mobsHave[$mob_id] < $mobsNeeded[$mob_id]) {
                         $completed = 'no';
                     }
                 }
                 // Maybe the character is turning in the quest...
                 if ($completed == 'yes' && $turnIn == true && isset($character_id) && isset($quest_id)) {
                     $completed = 'finished';
                 }
                 // Als de quest 'finished' is, dan moeten eventuele items uit de inventory verwijderd worden...
                 // Dat kan hier.
                 if ($completed == 'finished' && !empty($itemsNeeded)) {
                     foreach ($itemsNeeded as $item_id => $amount) {
                         for ($j = 1; $j <= $amount; $j++) {
                             $Inventory->deleteAll(array('Inventory.character_id' => $quest['CharactersQuest']['character_id'], 'Inventory.item_id' => $item_id));
                         }
                     }
                 }
                 $charactersQuestsData[$i]['completed'] = $completed;
             }
             // En voor het mooi, natuurlijk ook even de rewards geven...
             if ($completed == 'finished' && !empty($itemsRewards)) {
                 App::import('Model', 'Drop');
                 $Drop = new Drop();
                 foreach ($itemsRewards as $item_id => $amount) {
                     for ($j = 1; $j <= $amount; $j++) {
                         $data = array();
                         // Bagid en index opvragen
                         $bagIndex = $Drop->hasFreeSpace($quest['CharactersQuest']['character_id'], $item_id, true);
                         $data['character_id'] = $quest['CharactersQuest']['character_id'];
                         $data['item_id'] = $item_id;
                         $data['index'] = $bagIndex['index'];
                         $data['bag_id'] = $bagIndex['bag_id'];
                         $Inventory->create();
                         $Inventory->save($data);
                     }
                 }
             }
             if ($completed == 'finished' && !empty($statsRewards)) {
                 App::import('Model', 'CharactersStat');
                 $CharactersStat = new CharactersStat();
                 foreach ($statsRewards as $stat_id => $amount) {
                     $statData = array();
                     $statData['character_id'] = $quest['CharactersQuest']['character_id'];
                     // Kijken of deze stat al in de database bestaat
                     $someStat = $CharactersStat->find('first', array('conditions' => array('CharactersStat.stat_id' => $stat_id, 'CharactersStat.character_id' => $quest['CharactersQuest']['character_id'])));
                     if (!empty($someStat)) {
                         $statData['id'] = $someStat['CharactersStat']['id'];
                         $statData['amount'] = $someStat['CharactersStat']['amount'] + $amount;
                     } else {
                         $statData['amount'] = $amount;
                         $statData['stat_id'] = $stat_id;
                     }
                     $CharactersStat->create();
                     $CharactersStat->save($statData);
                 }
             }
             $i++;
         }
         $CharactersQuest->saveAll($charactersQuestsData);
     }
 }