Index: server/makefile
===================================================================
--- server/makefile	(revision 8a4ed742f6f3b488988cbe1838cfd2c753346ff4)
+++ server/makefile	(revision fbcfc352712a71a2fe77c0fa4146fac1ef437c72)
@@ -3,5 +3,5 @@
 FLAGS = $(LIB_FLAGS)
 COMMON_PATH = ../common
-DEPENDENCIES = Common.o Message.o Player.o WorldMap.o DataAccess.o
+DEPENDENCIES = Common.o Message.o Player.o WorldMap.o DataAccess.o Projectile.o
 
 server : server.cpp $(DEPENDENCIES)
@@ -20,4 +20,7 @@
 	$(CC) -c -o $@ $?
 
+Projectile.o : $(COMMON_PATH)/Projectile.cpp
+	$(CC) -c -o $@ $?
+
 %.o : %.cpp
 	$(CC) -c -o $@ $?
Index: server/server.cpp
===================================================================
--- server/server.cpp	(revision 8a4ed742f6f3b488988cbe1838cfd2c753346ff4)
+++ server/server.cpp	(revision fbcfc352712a71a2fe77c0fa4146fac1ef437c72)
@@ -31,4 +31,5 @@
 #include "../common/WorldMap.h"
 #include "../common/Player.h"
+#include "../common/Projectile.h"
 
 #include "DataAccess.h"
@@ -38,7 +39,8 @@
 // from used to be const. Removed that so I could take a reference
 // and use it to send messages
-bool processMessage(const NETWORK_MSG &clientMsg, struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedId, NETWORK_MSG &serverMsg, int sock, int &scoreBlue, int &scoreRed);
-
-void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers);
+bool processMessage(const NETWORK_MSG &clientMsg, struct sockaddr_in &from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedPlayerId, NETWORK_MSG &serverMsg, int sock, int &scoreBlue, int &scoreRed);
+
+void updateUnusedPlayerId(unsigned int& id, map<unsigned int, Player>& mapPlayers);
+void updateUnusedProjectileId(unsigned int& id, map<unsigned int, Projectile>& mapProjectiles);
 
 // this should probably go somewhere in the common folder
@@ -83,5 +85,6 @@
    NETWORK_MSG clientMsg, serverMsg;
    map<unsigned int, Player> mapPlayers;
-   unsigned int unusedId = 1;
+   map<unsigned int, Projectile> mapProjectiles;
+   unsigned int unusedPlayerId = 1, unusedProjectileId = 1;
    int scoreBlue, scoreRed;
 
@@ -142,4 +145,5 @@
          timeLastUpdated = curTime;
 
+         // move all players
          // maybe put this in a separate method
          map<unsigned int, Player>::iterator it;
@@ -317,4 +321,87 @@
                }
             }
+
+            // check if the player's attack animation is complete
+            if (it->second.isAttacking && it->second.timeAttackStarted+it->second.attackCooldown <= getCurrentMillis()) {
+               it->second.isAttacking = false;
+
+               //send everyone an ATTACK message
+               cout << "about to broadcast attack" << endl;
+
+               serverMsg.type = MSG_TYPE_ATTACK; 
+               memcpy(serverMsg.buffer, &it->second.id, 4);
+               memcpy(serverMsg.buffer+4, &it->second.targetPlayer, 4);
+
+               map<unsigned int, Player>::iterator it2;
+               for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++)
+               {
+                  if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 )
+                     error("sendMessage");
+               }
+
+               if (it->second.attackType == Player::ATTACK_MELEE) {
+                  Player* target = &mapPlayers[it->second.targetPlayer];
+
+                  target->health -= it->second.damage;
+                  if (target->health < 0)
+                     target->health = 0;
+
+                  serverMsg.type = MSG_TYPE_PLAYER;
+                  target->serialize(serverMsg.buffer);
+               }else if (it->second.attackType == Player::ATTACK_RANGED) {
+                  Projectile proj(it->second.pos.x, it->second.pos.y, it->second.targetPlayer, it->second.damage);
+                  proj.id = unusedProjectileId;
+                  updateUnusedProjectileId(unusedProjectileId, mapProjectiles);
+                  mapProjectiles[proj.id] = proj;
+
+                  serverMsg.type = MSG_TYPE_PROJECTILE;
+                  memcpy(serverMsg.buffer, &it->second.pos.x, 4);
+                  memcpy(serverMsg.buffer+4, &it->second.pos.y, 4);
+                  memcpy(serverMsg.buffer+8, &it->second.targetPlayer, 4);
+               }else {
+                  cout << "Invalid attack type: " << it->second.attackType << endl;
+               }
+
+               // broadcast either a PLAYER or PROJECTILE message
+               for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++)
+               {
+                  if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 )
+                     error("sendMessage");
+               }
+            }
+         }
+
+         // move all projectiles
+         map<unsigned int, Projectile>::iterator itProj;
+         for (itProj = mapProjectiles.begin(); itProj != mapProjectiles.end(); itProj++) {
+            if (itProj->second.move(mapPlayers)) {
+               // send a REMOVE_PROJECTILE message
+               serverMsg.type = MSG_TYPE_REMOVE_PROJECTILE;
+               memcpy(serverMsg.buffer, &itProj->second.id, 4);
+               mapProjectiles.erase(itProj->second.id);
+
+               map<unsigned int, Player>::iterator it2;
+               for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++)
+               {
+                  if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 )
+                     error("sendMessage");
+               }
+
+               // send a PLAYER message after dealing damage
+               Player* target = &mapPlayers[it->second.targetPlayer];
+
+               target->health -= itProj->second.damage;
+               if (target->health < 0)
+                  target->health = 0;
+
+               serverMsg.type = MSG_TYPE_PLAYER;
+               target->serialize(serverMsg.buffer);
+
+               for (it2 = mapPlayers.begin(); it2 != mapPlayers.end(); it2++)
+               {
+                  if ( sendMessage(&serverMsg, sock, &(it2->second.addr)) < 0 )
+                     error("sendMessage");
+               }
+            }
          }
       }
@@ -323,5 +410,5 @@
 
       if (n >= 0) {
-         broadcastResponse = processMessage(clientMsg, from, mapPlayers, gameMap, unusedId, serverMsg, sock, scoreBlue, scoreRed);
+         broadcastResponse = processMessage(clientMsg, from, mapPlayers, gameMap, unusedPlayerId, serverMsg, sock, scoreBlue, scoreRed);
 
          if (broadcastResponse)
@@ -350,5 +437,5 @@
 }
 
-bool processMessage(const NETWORK_MSG& clientMsg, struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedId, NETWORK_MSG& serverMsg, int sock, int &scoreBlue, int &scoreRed)
+bool processMessage(const NETWORK_MSG& clientMsg, struct sockaddr_in& from, map<unsigned int, Player>& mapPlayers, WorldMap* gameMap, unsigned int& unusedPlayerId, NETWORK_MSG& serverMsg, int sock, int &scoreBlue, int &scoreRed)
 {
    DataAccess da;
@@ -407,6 +494,6 @@
             serverMsg.type = MSG_TYPE_PLAYER;
 
-            updateUnusedId(unusedId, mapPlayers);
-            p->id = unusedId;
+            updateUnusedPlayerId(unusedPlayerId, mapPlayers);
+            p->id = unusedPlayerId;
             cout << "new player id: " << p->id << endl;
             p->setAddr(from);
@@ -472,5 +559,5 @@
 
             serverMsg.type = MSG_TYPE_LOGIN;
-            mapPlayers[unusedId] = *p;
+            mapPlayers[unusedPlayerId] = *p;
          }
 
@@ -499,6 +586,6 @@
          else
          {
-            if (p->id < unusedId)
-               unusedId = p->id;
+            if (p->id < unusedPlayerId)
+               unusedPlayerId = p->id;
             mapPlayers.erase(p->id);
             strcpy(serverMsg.buffer, "You have successfully logged out.");
@@ -672,5 +759,4 @@
          mapPlayers[id].serialize(serverMsg.buffer);
 
-         map<unsigned int, Player>::iterator it2;
          broadcastResponse = true;
 
@@ -686,5 +772,11 @@
          memcpy(&targetId, clientMsg.buffer+4, 4);
 
+         Player* source = &mapPlayers[id];
+         source->timeAttackStarted = getCurrentMillis();
+         source->targetPlayer = targetId;
+
          serverMsg.type = MSG_TYPE_START_ATTACK;
+         memcpy(serverMsg.buffer, &id, 4);
+         memcpy(serverMsg.buffer+4, &targetId, 4);
          broadcastResponse = true;
 
@@ -694,12 +786,5 @@
       {
          cout << "Received am ATTACK message" << endl;
-
-         int id, targetId;
-
-         memcpy(&id, clientMsg.buffer, 4);
-         memcpy(&targetId, clientMsg.buffer+4, 4);
-
-         serverMsg.type = MSG_TYPE_ATTACK;
-         broadcastResponse = true;
+         cout << "ERROR: Clients should not send ATTACK messages" << endl;
 
          break;
@@ -718,7 +803,13 @@
 }
 
-void updateUnusedId(unsigned int& id, map<unsigned int, Player>& mapPlayers)
+void updateUnusedPlayerId(unsigned int& id, map<unsigned int, Player>& mapPlayers)
 {
    while (mapPlayers.find(id) != mapPlayers.end())
       id++;
 }
+
+void updateUnusedProjectileId(unsigned int& id, map<unsigned int, Projectile>& mapProjectiles)
+{
+   while (mapProjectiles.find(id) != mapProjectiles.end())
+      id++;
+}
