#include "servership.h"
#include "servergame.h"
#include "serverdata.h"
#include "scorevals.h"


int ShipToShipCollision(int ship1, int ship2);
int ShotToShipCollision(int obj, int ship);
int PowerupToShipCollision(int obj, int ship);
int AsteroidToShipCollision(int obj, int ship);
int NukeToShipCollision(int obj, int ship);
int NukeExplosionToShipCollision(int obj, int ship);
int ShotToAsteroidCollision(int obj1, int obj2);
int ShotToPowerupCollision(int obj1, int obj2);
int AsteroidToAsteroidCollision(int obj1, int obj2);
int AsteroidToPowerupCollision(int obj1, int obj2);
int AsteroidToNukeCollision(int obj1, int obj2);
int AsteroidToNukeExplosionCollision(int obj1, int obj2);
int PowerupToPowerupCollision(int obj1, int obj2);


int (*ObjectToObjectCollisionFunctions[MAX_TYPES][MAX_TYPES])(int, int);
int (*ObjectToShipCollisionFunctions[MAX_TYPES])(int, int);


void InitCollisionFunctions()
{
  int i;
  int j;

  for (i=0; i<MAX_TYPES; i++) {
    for (j=0; j<MAX_TYPES; j++) {
      ObjectToObjectCollisionFunctions[i][j]=NULL;
    }
    ObjectToShipCollisionFunctions[i]=NULL;
  }

  ObjectToShipCollisionFunctions[SHOT_TYPE]=ShotToShipCollision;
  for (i=0; i<NUM_POWERUPS; i++) {
    ObjectToShipCollisionFunctions[SHIELD_POWERUP_TYPE+i]=PowerupToShipCollision;
  }
  ObjectToShipCollisionFunctions[NUKE_TYPE]=NukeToShipCollision;
  ObjectToShipCollisionFunctions[NUKE_EXPLOSION_TYPE]=NukeExplosionToShipCollision;
  ObjectToShipCollisionFunctions[ASTEROID_TYPE]=AsteroidToShipCollision;

  ObjectToObjectCollisionFunctions[SHOT_TYPE][ASTEROID_TYPE]=ShotToAsteroidCollision;
  for (i=0; i<NUM_POWERUPS; i++) {
    ObjectToObjectCollisionFunctions[SHOT_TYPE][SHIELD_POWERUP_TYPE+i]=ShotToPowerupCollision;
  }
  ObjectToObjectCollisionFunctions[ASTEROID_TYPE][ASTEROID_TYPE]=AsteroidToAsteroidCollision;
  for (i=0; i<NUM_POWERUPS; i++) {
    ObjectToObjectCollisionFunctions[ASTEROID_TYPE][SHIELD_POWERUP_TYPE+i]=AsteroidToPowerupCollision;
  }
  ObjectToObjectCollisionFunctions[ASTEROID_TYPE][NUKE_TYPE]=AsteroidToNukeCollision;
  ObjectToObjectCollisionFunctions[ASTEROID_TYPE][NUKE_EXPLOSION_TYPE]=AsteroidToNukeExplosionCollision;
  for (i=0; i<NUM_POWERUPS; i++) {
    for (j=0; j<NUM_POWERUPS; j++) {
      ObjectToObjectCollisionFunctions[SHIELD_POWERUP_TYPE+i][SHIELD_POWERUP_TYPE+j]=PowerupToPowerupCollision;
    }
  }
}


int ShipToShipCollision(int ship1, int ship2)
{
  int Damage;

  Damage=BounceObjects(ServerShips[ship1], ServerShips[ship2]);

  if (!ServerShips[ship1]->Action.shield || !ServerShips[ship1]->Shield) {
    if (ServerShips[ship1]->TakeDamage(Damage)) {
      if (ServerGameType==DEATHMATCH) {
        ServerShips[ship1]->Score--;
        ServerShips[ship2]->Score++;
      } else if (ServerGameType==FREE_FOR_ALL || ServerGameType==SINGLE_PLAYER) {
        ServerShips[ship2]->Score+=ShipScore;
      }
    }
  } else {
    if (Damage) {
      AddSound(ship1, &ServerShips[ship1]->Position, PingSound);
    }
  }

  if (!ServerShips[ship2]->Action.shield || !ServerShips[ship2]->Shield) {
    if (ServerShips[ship2]->TakeDamage(Damage)) {
      if (ServerGameType==DEATHMATCH) {
        ServerShips[ship1]->Score++;
        ServerShips[ship2]->Score--;
      } else if (ServerGameType==FREE_FOR_ALL || ServerGameType==SINGLE_PLAYER) {
        ServerShips[ship1]->Score+=ShipScore;
      }
      return(1);
    }
  } else {
    if (Damage) {
      AddSound(ship2, &ServerShips[ship2]->Position, PingSound);
    }
  }

  return(0);
}


int ShotToShipCollision(int obj, int ship)
{
  int rc;
  int Damage;

  if (ship==ServerObjects[obj]->PlayerNum) {
    return(0);
  }

  rc=BounceObjects(ServerShips[ship], ServerObjects[obj]);
  if (ServerShips[ship]->Action.shield && ServerShips[ship]->Shield && rc) {
    AddSoundAll(&ServerShips[ship]->Position, PingSound);
  } else {
    Damage=ShotDamage;
    if (ServerShips[ServerObjects[obj]->PlayerNum]->Bot) {
      Damage=(int)((float)Damage*BotRatio);
    }

    if (ServerShips[ship]->TakeDamage(Damage)) {
      if (ServerGameType==DEATHMATCH) {
        ServerShips[ServerObjects[obj]->PlayerNum]->Score++;
      } else {
        ServerShips[ServerObjects[obj]->PlayerNum]->Score+=ShipScore;
      }
      return(1);
    } else {
      CreateExplosion(obj, 0);
    }
    delete ServerObjects[obj];
    ServerObjects[obj]=NULL;
  }

  return(0);
}


int PowerupToShipCollision(int obj, int ship)
{
  AddSound(ship, &ServerShips[ship]->Position, PrizeSound);

  if (ServerObjects[obj]->ObjectType==SHIELD_POWERUP_TYPE) {
    ServerShips[ship]->IncreaseShield(ShieldPowerupValue);
  } else if (ServerObjects[obj]->ObjectType==ARMOR_POWERUP_TYPE) {
    ServerShips[ship]->IncreaseArmor(ArmorPowerupValue);
  } else if (ServerObjects[obj]->ObjectType==HYPERWARP_POWERUP_TYPE) {
    ServerShips[ship]->Warps++;
  } else if (ServerObjects[obj]->ObjectType==NUKE_POWERUP_TYPE) {
    ServerShips[ship]->Nukes++;
  }

  delete ServerObjects[obj];
  ServerObjects[obj]=NULL;

  return(0);
}


int NukeToShipCollision(int obj, int ship)
{
  if (ship==ServerObjects[obj]->PlayerNum) {
    return(0);
  }

  delete ServerObjects[obj];
  ServerObjects[obj]=NULL;

  return(0);
}


int NukeExplosionToShipCollision(int obj, int ship)
{
  if (!ServerObjects[obj]->PlayersHit[ship]) {
    if (ServerShips[ship]->Action.shield && ServerShips[ship]->Shield) {
      ServerShips[ship]->DecreaseShield(NukeShieldDrain);
      ServerObjects[obj]->PlayersHit[ship]=1;
      return(0);
    } else {
      if (ServerShips[ship]->TakeDamage(NukeDamage)) {
        if (ServerGameType==DEATHMATCH) {
          ServerShips[ServerObjects[obj]->PlayerNum]->Score++;
        } else {
          ServerShips[ServerObjects[obj]->PlayerNum]->Score+=ShipScore;
        }
      }
    }
    ServerObjects[obj]->PlayersHit[ship]=1;
    return(1);
  }
  return(0);
}


int AsteroidToShipCollision(int obj, int ship)
{
  if (ServerShips[ship]->Action.shield && ServerShips[ship]->Shield) {
    if (BounceObjects(ServerShips[ship], ServerObjects[obj])) {
      AddSoundAll(&ServerShips[ship]->Position, PingSound);
    }
    return(0);
  } else {
    if (ServerShips[ship]->TakeDamage(BounceObjects(ServerShips[ship], ServerObjects[obj]))) {
      if (ServerGameType==DEATHMATCH) {
        ServerShips[ship]->Score--;
      } else if (ServerGameType==FREE_FOR_ALL) {
        ServerShips[ship]->Score-=ShipScore;
      }
    }
    return(1);
  }
}


int ShotToAsteroidCollision(int obj1, int obj2)
{
  CreateExplosion(obj1, 0);
  AddSoundAll(&ServerObjects[obj1]->Position, ExplosionSound);

  if (ServerObjects[obj2]->ObjectSize > MinRockSize) {
    CreateExplosionRandomRock(obj2);
  }
  if (ServerShips[ServerObjects[obj1]->PlayerNum] && ServerGameType!=DEATHMATCH) {
    ServerShips[ServerObjects[obj1]->PlayerNum]->Score+=AsteroidScore;
  }

  delete ServerObjects[obj1];
  ServerObjects[obj1]=NULL;
  delete ServerObjects[obj2];
  ServerObjects[obj2]=NULL;

  return(3);
}


int ShotToPowerupCollision(int obj1, int obj2)
{
  if (ServerShips[ServerObjects[obj1]->PlayerNum]) {
    AddSound(ServerObjects[obj1]->PlayerNum, &ServerShips[ServerObjects[obj1]->PlayerNum]->Position, IdiotSound);
  }

  CreateExplosion(obj2, 0);
  AddSoundAll(&ServerObjects[obj2]->Position, ExplosionSound);

  delete ServerObjects[obj1];
  ServerObjects[obj1]=NULL;
  delete ServerObjects[obj2];
  ServerObjects[obj2]=NULL;

  return(3);
}


int AsteroidToAsteroidCollision(int obj1, int obj2)
{
  if (BounceObjects(ServerObjects[obj1], ServerObjects[obj2])) {
    AddSoundAll(&ServerObjects[obj1]->Position, CrunchSound);
  }

  return(0);
}


int AsteroidToPowerupCollision(int obj1, int obj2)
{
  if (BounceObjects(ServerObjects[obj1], ServerObjects[obj2])) {
    AddSoundAll(&ServerObjects[obj2]->Position, PingSound);
  }

  return(0);
}


int AsteroidToNukeCollision(int obj1, int obj2)
{
  delete ServerObjects[obj2];
  ServerObjects[obj2]=NULL;

  return(2);
}


int AsteroidToNukeExplosionCollision(int obj1, int obj2)
{
  CreateExplosion(obj1, 0);
  AddSoundAll(&ServerObjects[obj1]->Position, ExplosionSound);

  if (ServerShips[ServerObjects[obj1]->PlayerNum] && ServerGameType!=DEATHMATCH) {
    ServerShips[ServerObjects[obj1]->PlayerNum]->Score+=AsteroidScore;
  }

  delete ServerObjects[obj1];
  ServerObjects[obj1]=NULL;

  return(1);
}


int PowerupToPowerupCollision(int obj1, int obj2)
{
  if (BounceObjects(ServerObjects[obj1], ServerObjects[obj2])) {
    AddSoundAll(&ServerObjects[obj1]->Position, PingSound);
  }

  return(0);
}
