#include "main.h"


int samp_get_version(void)
{
   static const void *samp_dll = dll_baseptr_get("samp.dll");

   if(samp_dll == NULL)
      return SAMP_VERSION_UNKNOWN;

   if(!memcmp_safe((uint8_t *)samp_dll + 0x00090E6D, hex_to_bin("53412D4D"), 4))
      return SAMP_VERSION_UNKNOWN;

   return SAMP_VERSION_1;
}

int samp_name_tags_status(int enabled)
{
   static struct patch_set patch = {
         "Remove player status", 0, 0, {
         { 5, (void *)((uint8_t *)dll_baseptr_get("samp.dll") + 0x00008992),
              (uint8_t *)"\xE8\x69\x45\x00\x00",
              (uint8_t *)"\x83\xC4\x18\x90\x90", NULL }
      } };

   if(enabled)
      return patcher_remove(&patch);
   else
      return patcher_install(&patch);
}


D3DCOLOR samp_color_get(int id)
{
   static const void *samp_dll = dll_baseptr_get("samp.dll");
   D3DCOLOR *color_table;

   if(samp_dll == NULL || samp_get_version() != SAMP_VERSION_1 || id < 0 || id >= 103)
      return D3DCOLOR_ARGB(0xFF, 0x99, 0x99, 0x99);

   switch(id)
   {
   case 100: return D3DCOLOR_ARGB(0xFF, 0x88, 0x88, 0x88);
   case 101: return D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0xAA);
   case 102: return D3DCOLOR_ARGB(0xFF, 0x63, 0xC0, 0xE2);
   }

   color_table = (D3DCOLOR *)((uint8_t *)samp_dll + 0x000B1814);

   return (color_table[id] >> 8) | 0xFF000000;
}


struct samp_chat_info *samp_chat_info_get(void)
{
   static const void *samp_dll = dll_baseptr_get("samp.dll");

   if(samp_dll == NULL || samp_get_version() != SAMP_VERSION_1)
      return NULL;

   return (struct samp_chat_info *)(UINT_PTR)*(uint32_t *)((uint8_t *)samp_dll + 0x000B2C24);
}


int samp_is_chatting(void)
{
   struct samp_chat_input_info *info = samp_chat_input_info_get();

   return (info != NULL && info->enabled);
}


struct samp_chat_input_info * samp_chat_input_info_get(void)
{
   static const void *samp_dll = dll_baseptr_get("samp.dll");

   if(samp_dll == NULL || samp_get_version() != SAMP_VERSION_1)
      return 0;

   return (struct samp_chat_input_info *)(UINT_PTR)*(uint32_t *)((uint8_t *)samp_dll + 0x000B2C28);
}


struct samp_kill_info *samp_kill_info_get(void)
{
   static const void *samp_dll = dll_baseptr_get("samp.dll");

   if(samp_dll == NULL || samp_get_version() != SAMP_VERSION_1)
      return NULL;

   return (struct samp_kill_info *)(UINT_PTR)*(uint32_t *)((uint8_t *)samp_dll + 0x000B2C2C);
}



/* 021BDA03  |.  8B15 302C2602 mov edx,dword ptr ds:[2262C30]
   021BDA09  |.  8B3A          mov edi,dword ptr ds:[edx]
*/
struct samp_player_list *samp_player_list_get(void)
{
   static const void *samp_dll = dll_baseptr_get("samp.dll");
   uint32_t *ptr;
   uint32_t *edx;
   void     *edi;

   if(samp_dll == NULL || samp_get_version() != SAMP_VERSION_1)
      return NULL;

   ptr = (uint32_t *)((uint8_t *)samp_dll + 0x000B2C30);
   edx = (uint32_t *)(UINT_PTR)*ptr;
   if(edx == NULL)
      return NULL;
   edi = (void     *)(UINT_PTR)*edx;

   return (struct samp_player_list *)edi;
}



int samp_player_count(void)
{
   struct samp_player_list *spl = samp_player_list_get();
   int count = 0;
   int i;

   if(spl == NULL)
      return 0;

   for(i=0; i<102; i++)
   {
      if(spl->alloc_map[i] != 1)
         continue;

      count++;
   }

   return count + 1;
}


const char *samp_player_name_get(int id)
{
   struct samp_player_list *spl = samp_player_list_get();

   if(spl == NULL || id < 0 || id >= SAMP_PLAYER_MAX)
      return NULL;

   if(id == spl->self_id)
      return spl->self_name;

   if(spl->alloc_map[id] != 1)
      return NULL;

   return spl->name[id];
}


struct actor_info *samp_player_actor_info_get(int id)
{
   struct samp_player_list *spl = samp_player_list_get();

   if(spl == NULL || id < 0 || id >= SAMP_PLAYER_MAX)
      return NULL;

   if(id == spl->self_id)
      return actor_info_get(ACTOR_SELF, 0);

   if(spl->alloc_map[id] != 1)
      return NULL;

   if(spl->player_info[id] == NULL)
      return NULL;

   if(spl->player_info[id]->actor == NULL)
      return NULL;

   return *spl->player_info[id]->actor;
}


int samp_player_get_id_by_actor(struct actor_info *info)
{
   struct samp_player_list *spl = samp_player_list_get();
   int i;

   if(spl == NULL)
      return -1;

   if(actor_info_get(ACTOR_SELF, 0) == info)
      return spl->self_id;

   for(i=0; i<SAMP_PLAYER_MAX; i++)
   {
      if(spl->alloc_map[i] != 1)
         continue;

      if(spl->player_info[i] == NULL ||
         spl->player_info[i]->actor == NULL)
         continue;

      if(*spl->player_info[i]->actor == info)
         return i;
   }

   return -1;
}


/* this is retarded */
int samp_player_position_get(int id, float pos[3])
{
   struct samp_player_list *spl = samp_player_list_get();
   struct actor_info *self = actor_info_get(ACTOR_SELF, 0);
   struct actor_info *actor = NULL;
   struct vehicle_info *vehicle = NULL;

   if(spl->alloc_map[id] != 1)
      return 0;

   if(spl->player_info[id] == NULL)
      return 0;

   if(spl->player_info[id]->actor != NULL)
      actor = *spl->player_info[id]->actor;
   if(spl->player_info[id]->vehicle != NULL)
      vehicle = *spl->player_info[id]->vehicle;

   if(actor == NULL && vehicle == NULL)
      return 0;

   /* near - on foot:    &actor->base.matrix[4*3]
      far  - on foot:    info->actor_pos
      near - in vehicle: &actor->base.matrix[4*3]
      far  - in vehicle: info->vehicle_pos
      near - passenger:  &actor->base.matrix[4*3]
      far  - passenger:  &actor->base.matrix[4*3]
   */

   if(vehicle != NULL && actor->vehicle == vehicle && vehicle->passengers[0] == actor)
   {
      /* driver of a vehicle */
      vect3_copy(spl->player_info[id]->vehicle_pos, pos);
   }
   else if(vehicle != NULL)
   {
      /* passenger of a vehicle */
      vect3_copy(&actor->base.matrix[4*3], pos);
   }
   else
   {
      /* on foot */
      vect3_copy(spl->player_info[id]->actor_pos, pos);
   }

   if(self != NULL)
   {
      if(vect3_dist(&self->base.matrix[4*3], pos) < 100.0f)
         vect3_copy(&actor->base.matrix[4*3], pos);
   }

   /* detect zombies */
   if(vect3_near_zero(pos))
      vect3_copy(&actor->base.matrix[4*3], pos);

   return !vect3_near_zero(pos);
}

