114 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			114 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			C
		
	
	
| #include "npc.h"
 | |
| #include "tile.h"
 | |
| #include "stubs.h" // for interface
 | |
| #include "game.h" // for current_map
 | |
| 
 | |
| /**** npcThink
 | |
|   Catch-all function for processing each NPC's think operations - these operations include decision making and the attempt to act on that decision.
 | |
| 
 | |
| Arguments: struct Tile *npc
 | |
| Returns: void
 | |
| ****/
 | |
| void npcThink(struct Tile *npc) {
 | |
|   struct NpcTile *npc_data = npc->data;
 | |
|   struct Tile *target;
 | |
|   switch (npc_data->behavior) {
 | |
|     case BEHAVE_AGGRESSIVE:
 | |
|       if (!npc_data->target) { // find a player
 | |
|         if ((target = npcFindTile(npc, PLAYER))) {
 | |
|           interfacePrint("The nupi, fueled by bloodlust, shrieks in rage");
 | |
|           npc_data->target = target;
 | |
|         }
 | |
|       } else {
 | |
|         npcMoveToTarget(npc, npc_data);
 | |
|       }
 | |
|       break;
 | |
|     case BEHAVE_WANDER:
 | |
|       npcMoveRandom(npc);
 | |
|       break;
 | |
|   }
 | |
| }
 | |
| /**** npcMoveToTarget
 | |
|   Called from npcThink, this function attempts to move the given NPC to its target's location.
 | |
| 
 | |
| Arguments: struct Tile *npc, struct NpcTile *npc_tile
 | |
| Returns: void
 | |
| TODO: should return the change in x/y. It is redundant to pass NpcTile as well, but since parent operations hold that info as well, it makes some sense to pass it as well - not sure if this should be changed.
 | |
| ****/
 | |
| void npcMoveToTarget(struct Tile *npc, struct NpcTile *npc_data) {
 | |
|   int current_x = npc->x;
 | |
|   int current_y = npc->y;
 | |
|   struct Tile *target_tile;
 | |
|   target_tile = npc_data->target;
 | |
|   if (target_tile) {
 | |
|     if (npc->x < target_tile->x) {
 | |
|       current_x++;
 | |
|     } else if (npc->x > target_tile->x) {
 | |
|       current_x--;
 | |
|     }
 | |
|     if (npc->y < target_tile->y) {
 | |
|       current_y++;
 | |
|     } else if (npc->y > target_tile->y) {
 | |
|       current_y--;
 | |
|     }
 | |
|     if (!gameCollision(current_x, current_y)) {
 | |
|       gameMoveTile(npc, current_x, current_y);
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**** npcMoveRandom
 | |
|   Simply moves the given NPC in a random direction
 | |
| 
 | |
| Arguments: struct Tile *npc
 | |
| Returns: void
 | |
| ****/
 | |
| void npcMoveRandom(struct Tile *npc) {
 | |
|   int target_x = npc->x + (roll(0, 2)-1);
 | |
|   int target_y = npc->y + (roll(0, 2)-1);
 | |
|   if (!gameCollision(target_x, target_y)) {
 | |
|     gameMoveTile(npc, target_x, target_y);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**** npcFindTile
 | |
|   Dumb function that blindly iterates through a square around the NPC until a Tile of tile_type(PLAYER, ITEM, etc.) is (hopefully) found. Upon being found, returns the found Tile.
 | |
| 
 | |
| Arguments: struct Tile *npc, int tile_type
 | |
| Returns: struct Tile*
 | |
| TODO: This function should be removed and re-implemented in map.c as a generic findTile function that takes start x, start y, width, height (or radius?), and the target tile type.
 | |
| TODO: Also should have a version that takes a Tile struct as the target instead of a type id.
 | |
| ****/
 | |
| struct Tile *npcFindTile(struct Tile *npc, int tile_type) {
 | |
|   struct Tile *final_target;
 | |
|   struct NpcTile *npc_data = npc->data;
 | |
|   struct Tile *current_tile;
 | |
|   int step_x = npc->x - npc_data->vision;
 | |
|   int step_y = npc->y - npc_data->vision;
 | |
|   int end_x = npc->x + npc_data->vision;
 | |
|   int end_y = npc->y + npc_data->vision;
 | |
|   int found_x = 0;
 | |
|   int found_y = 0;
 | |
|   while (step_x < end_x) {
 | |
|     step_y = npc->y - (npc_data->vision);
 | |
|     while (step_y < end_y) {
 | |
|       if (step_x >= 0 && step_y >= 0 && step_x < current_map->width && step_y < current_map->height) {
 | |
|         current_tile = ¤t_map->matrix[step_x][step_y];
 | |
|         while (current_tile) {
 | |
|           if (current_tile->tid == tile_type) {
 | |
|             if ( ( (npc->x-step_x) + (npc->y-step_y)) < (npc->x-found_x + npc->y-found_y) ) {
 | |
|               found_x = step_x;
 | |
|               found_y = step_y;
 | |
|               final_target = current_tile;
 | |
|             }
 | |
|           }
 | |
|           current_tile = current_tile->next;
 | |
|         }
 | |
|       }
 | |
|       step_y++;
 | |
|     }
 | |
|     step_x++;
 | |
|   }
 | |
|   return final_target;
 | |
| }
 |