void actLadder(Entity *my) { int playercount=0; double dist; int i, c; LADDER_AMBIENCE--; if( LADDER_AMBIENCE<=0 ) { LADDER_AMBIENCE = TICKS_PER_SECOND*30; playSoundEntityLocal( my, 149, 64 ); } // use ladder (climb) if( multiplayer!=CLIENT ) { for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { for( c=0; c<MAXPLAYERS; c++ ) { if( client_disconnected[c] || players[c] == NULL ) continue; else playercount++; dist = sqrt( pow(my->x-players[c]->x,2) + pow(my->y-players[c]->y,2) ); if( dist > TOUCHRANGE ) { messagePlayer(i,language[505]); return; } } if( playercount==1 ) messagePlayer(i,language[506]); else messagePlayer(i,language[507]); loadnextlevel=TRUE; if( secretlevel ) { switch( currentlevel ) { case 3: for( c=0; c<MAXPLAYERS; c++ ) steamAchievementClient(c,"BARONY_ACH_THUNDERGNOME"); break; } } if( LADDER_SECRET ) secretlevel = (secretlevel==FALSE); // toggle level lists return; } } } } }
void actFountain(Entity* my) { Entity* entity; //messagePlayer(0, "actFountain()"); //TODO: Temporary mechanism testing code. /* if( multiplayer != CLIENT ) { if (my->skill[28]) { //All it does is change its sprite to sink if it's powered. if (my->skill[28] == 1) { my->sprite = 163; } else { my->sprite = 164; } } }*/ //****************END TEST CODE*************** //TODO: Sounds. // spray water if ( my->skill[0] > 0 ) { #define FOUNTAIN_AMBIENCE my->skill[7] FOUNTAIN_AMBIENCE--; if ( FOUNTAIN_AMBIENCE <= 0 ) { FOUNTAIN_AMBIENCE = TICKS_PER_SECOND * 6; playSoundEntityLocal(my, 135, 32 ); } entity = spawnGib(my); entity->flags[INVISIBLE] = false; entity->y -= 2; entity->z -= 8; entity->flags[SPRITE] = false; entity->flags[NOUPDATE] = true; entity->flags[UPDATENEEDED] = false; entity->skill[4] = 7; entity->sprite = 4; entity->yaw = (rand() % 360) * PI / 180.0; entity->pitch = (rand() % 360) * PI / 180.0; entity->roll = (rand() % 360) * PI / 180.0; entity->vel_x = 0; entity->vel_y = 0; entity->vel_z = .25; entity->fskill[3] = 0.03; } // the rest of the function is server-side. if ( multiplayer == CLIENT ) { return; } //Using the fountain (TODO: Monsters using it?). int i; for (i = 0; i < MAXPLAYERS; ++i) { if ( (i == 0 && selectedEntity == my) || (client_selected[i] == my) ) { if (inrange[i]) //Act on it only if the player (or monster, if/when this is changed to support monster interaction?) is in range. { //First check that it's not depleted. if (my->skill[0] == 0) { //Depleted messagePlayer(i, language[467]); } else { if (players[i]->entity->flags[BURNING]) { messagePlayer(i, language[468]); players[i]->entity->flags[BURNING] = false; serverUpdateEntityFlag(players[i]->entity, BURNING); steamAchievementClient(i, "BARONY_ACH_HOT_SHOWER"); } switch (my->skill[1]) { case 0: { playSoundEntity(players[i]->entity, 52, 64); //Spawn succubus. Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0); Entity* spawnedMonster = nullptr; if ( !strncmp(map.name, "Underworld", 10) ) { Monster creature = SUCCUBUS; if ( rand() % 2 ) { creature = INCUBUS; } for ( int c = 0; spawnedMonster == nullptr && c < 5; ++c ) { switch ( c ) { case 0: spawnedMonster = summonMonster(creature, my->x, my->y); break; case 1: spawnedMonster = summonMonster(creature, my->x + 16, my->y); break; case 2: spawnedMonster = summonMonster(creature, my->x - 16, my->y); break; case 3: spawnedMonster = summonMonster(creature, my->x, my->y + 16); break; case 4: spawnedMonster = summonMonster(creature, my->x, my->y - 16); break; } } if ( spawnedMonster ) { if ( creature == INCUBUS ) { messagePlayerColor(i, color, language[2519]); Stat* tmpStats = spawnedMonster->getStats(); if ( tmpStats ) { strcpy(tmpStats->name, "lesser incubus"); } } else { messagePlayerColor(i, color, language[469]); } } } else if ( currentlevel < 10 ) { messagePlayerColor(i, color, language[469]); spawnedMonster = summonMonster(SUCCUBUS, my->x, my->y); } else if ( currentlevel < 20 ) { if ( rand() % 2 ) { spawnedMonster = summonMonster(INCUBUS, my->x, my->y); Stat* tmpStats = spawnedMonster->getStats(); if ( tmpStats ) { strcpy(tmpStats->name, "lesser incubus"); } messagePlayerColor(i, color, language[2519]); } else { messagePlayerColor(i, color, language[469]); spawnedMonster = summonMonster(SUCCUBUS, my->x, my->y); } } else { messagePlayerColor(i, color, language[2519]); spawnedMonster = summonMonster(INCUBUS, my->x, my->y); } break; } case 1: messagePlayer(i, language[470]); messagePlayer(i, language[471]); playSoundEntity(players[i]->entity, 52, 64); stats[i]->HUNGER += 100; players[i]->entity->modHP(5); break; case 2: { //Potion effect. Potion effect is stored in my->skill[3], randomly chosen when the fountain is created. messagePlayer(i, language[470]); Item* item = newItem(static_cast<ItemType>(POTION_WATER + my->skill[3]), static_cast<Status>(4), 0, 1, 0, false, NULL); useItem(item, i); // Long live the mystical fountain of TODO. break; } case 3: { // bless all equipment playSoundEntity(players[i]->entity, 52, 64); Uint32 textcolor = SDL_MapRGB(mainsurface->format, 0, 255, 255); messagePlayerColor(i, textcolor, language[471]); messagePlayer(i, language[473]); if ( stats[i]->helmet ) { stats[i]->helmet->beatitude++; } if ( stats[i]->breastplate ) { stats[i]->breastplate->beatitude++; } if ( stats[i]->gloves ) { stats[i]->gloves->beatitude++; } if ( stats[i]->shoes ) { stats[i]->shoes->beatitude++; } if ( stats[i]->shield ) { stats[i]->shield->beatitude++; } if ( stats[i]->weapon ) { stats[i]->weapon->beatitude++; } if ( stats[i]->cloak ) { stats[i]->cloak->beatitude++; } if ( stats[i]->amulet ) { stats[i]->amulet->beatitude++; } if ( stats[i]->ring ) { stats[i]->ring->beatitude++; } if ( stats[i]->mask ) { stats[i]->mask->beatitude++; } if ( multiplayer == SERVER && i > 0 ) { strcpy((char*)net_packet->data, "BLES"); net_packet->address.host = net_clients[i - 1].host; net_packet->address.port = net_clients[i - 1].port; net_packet->len = 4; sendPacketSafe(net_sock, -1, net_packet, i - 1); } break; } case 4: { // bless one piece of equipment playSoundEntity(players[i]->entity, 52, 64); Uint32 textcolor = SDL_MapRGB(mainsurface->format, 0, 255, 255); messagePlayerColor(i, textcolor, language[471]); //Choose only one piece of equipment to bless. //First, Figure out what equipment is available. std::vector<std::pair<Item*, Uint32>> items; if ( stats[i]->helmet ) { items.push_back(std::pair<Item*,int>(stats[i]->helmet, 0)); } if ( stats[i]->breastplate ) { items.push_back(std::pair<Item*,int>(stats[i]->breastplate, 1)); } if ( stats[i]->gloves ) { items.push_back(std::pair<Item*,int>(stats[i]->gloves, 2)); } if ( stats[i]->shoes ) { items.push_back(std::pair<Item*,int>(stats[i]->shoes, 3)); } if ( stats[i]->shield ) { items.push_back(std::pair<Item*,int>(stats[i]->shield, 4)); } if ( stats[i]->weapon ) { items.push_back(std::pair<Item*,int>(stats[i]->weapon, 5)); } if ( stats[i]->cloak ) { items.push_back(std::pair<Item*,int>(stats[i]->cloak, 6)); } if ( stats[i]->amulet ) { items.push_back(std::pair<Item*,int>(stats[i]->amulet, 7)); } if ( stats[i]->ring ) { items.push_back(std::pair<Item*,int>(stats[i]->ring, 8)); } if ( stats[i]->mask ) { items.push_back(std::pair<Item*,int>(stats[i]->mask, 9)); } if ( items.size() ) { messagePlayer(i, language[2592]); //"The fountain blesses a piece of equipment" //Randomly choose a piece of equipment. std::pair<Item*, Uint32> chosen = items[rand()%items.size()]; chosen.first->beatitude++; if ( multiplayer == SERVER && i > 0 ) { strcpy((char*)net_packet->data, "BLE1"); SDLNet_Write32(chosen.second, &net_packet->data[4]); net_packet->address.host = net_clients[i - 1].host; net_packet->address.port = net_clients[i - 1].port; net_packet->len = 8; sendPacketSafe(net_sock, -1, net_packet, i - 1); } } //Does nothing if no valid items. break; } default: break; } messagePlayer(i, language[474]); my->skill[0] = 0; //Dry up fountain. serverUpdateEntitySkill(my, my->skill[0]); //TODO: messagePlayersInSight() instead. } //Then perform the effect randomly determined when the fountain was created. return; } } } }
int boulderCheckAgainstEntity(Entity *my, Entity *entity) { if (!my || !entity) return 0; if( entity->behavior == &actPlayer || entity->behavior == &actMonster ) { if( entityInsideEntity( my, entity ) ) { Stat *stats = entity->getStats(); if( stats ) { if( entity->behavior==&actPlayer ) { Uint32 color = SDL_MapRGB(mainsurface->format,255,0,0); messagePlayerColor(entity->skill[2],color,language[455]); if( entity->skill[2] == clientnum ) { camera_shakex += .1; camera_shakey += 10; } else { strcpy((char *)net_packet->data,"SHAK"); net_packet->data[4]=10; // turns into .1 net_packet->data[5]=10; net_packet->address.host = net_clients[entity->skill[2]-1].host; net_packet->address.port = net_clients[entity->skill[2]-1].port; net_packet->len = 6; sendPacketSafe(net_sock, -1, net_packet, entity->skill[2]-1); } } playSoundEntity(my,181,128); playSoundEntity(entity,28,64); spawnGib(entity); entity->modHP(-80); entity->setObituary(language[1505]); if( entity->behavior==&actPlayer ) if( stats->HP<=0 ) steamAchievementClient(entity->skill[2],"BARONY_ACH_THROW_ME_THE_WHIP"); if( stats->HP > 0 ) { // spawn several rock items int i = 8+rand()%4; int c; for( c=0; c<i; c++ ) { Entity *entity = newEntity(-1,1,map.entities); entity->flags[INVISIBLE]=TRUE; entity->flags[UPDATENEEDED]=TRUE; entity->x = my->x - 4 + rand()%8; entity->y = my->y - 4 + rand()%8; entity->z = -6+rand()%12; entity->sizex = 4; entity->sizey = 4; entity->yaw = rand()%360 * PI/180; entity->vel_x = (rand()%20-10)/10.0; entity->vel_y = (rand()%20-10)/10.0; entity->vel_z = -.25 - (rand()%5)/10.0; entity->flags[PASSABLE] = TRUE; entity->behavior = &actItem; entity->flags[USERFLAG1] = TRUE; // no collision: helps performance entity->skill[10] = GEM_ROCK; // type entity->skill[11] = WORN; // status entity->skill[12] = 0; // beatitude entity->skill[13] = 1; // count entity->skill[14] = 0; // appearance entity->skill[15] = FALSE; // identified } double ox = my->x; double oy = my->y; // destroy the boulder playSoundEntity(my,67,128); list_RemoveNode(my->mynode); // on sokoban, destroying boulders spawns scorpions if( !strcmp(map.name,"Sokoban") ) { Entity *monster = summonMonster(SCORPION,ox,oy); if( monster ) { int c; for( c=0; c<MAXPLAYERS; c++ ) { Uint32 color = SDL_MapRGB(mainsurface->format,255,128,0); messagePlayerColor(c,color,language[406]); } } } return 1; } } } } else if( entity->behavior == &actGate || entity->behavior == &actBoulder || entity->behavior==&actChest || entity->behavior==&actHeadstone || entity->behavior==&actFountain || entity->behavior==&actSink ) { if( !entity->flags[PASSABLE] ) { if( entityInsideEntity( my, entity ) ) { // stop the boulder BOULDER_STOPPED=1; BOULDER_ROLLING=0; playSoundEntity(my,181,128); if( my->flags[PASSABLE] ) { my->flags[PASSABLE] = FALSE; if( multiplayer==SERVER ) serverUpdateEntityFlag(my,PASSABLE); } } } } else if( entity->behavior == &actDoor ) { if( entityInsideEntity( my, entity ) ) { playSoundEntity(entity,28,64); entity->skill[4] = 0; if( !entity->skill[0] ) entity->skill[6] = (my->x > entity->x); else entity->skill[6] = (my->y < entity->y); playSoundEntity(my,181,128); } } return 0; }
void actPortal(Entity *my) { int playercount=0; double dist; int i, c; if( !PORTAL_INIT ) { PORTAL_INIT=1; my->light = lightSphereShadow(my->x/16,my->y/16,3,255); } PORTAL_AMBIENCE--; if( PORTAL_AMBIENCE<=0 ) { PORTAL_AMBIENCE = TICKS_PER_SECOND*2; playSoundEntityLocal( my, 154, 128 ); } my->yaw += 0.01; // rotate slowly on my axis my->sprite = 254+(my->ticks/20)%4; // animate if( multiplayer==CLIENT ) return; // step through portal for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { for( c=0; c<MAXPLAYERS; c++ ) { if( client_disconnected[c] || players[c] == NULL ) continue; else playercount++; dist = sqrt( pow(my->x-players[c]->x,2) + pow(my->y-players[c]->y,2) ); if( dist > TOUCHRANGE ) { messagePlayer(i,language[505]); return; } } if( playercount==1 ) messagePlayer(i,language[510]); else messagePlayer(i,language[511]); loadnextlevel=TRUE; if( secretlevel ) { switch( currentlevel ) { case 9: { ; bool visiblegrave=FALSE; node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity->sprite==224 && !entity->flags[INVISIBLE] ) { visiblegrave=TRUE; break; } } if( visiblegrave ) for( c=0; c<MAXPLAYERS; c++ ) steamAchievementClient(c,"BARONY_ACH_ROBBING_THE_CRADLE"); break; } case 14: for( c=0; c<MAXPLAYERS; c++ ) steamAchievementClient(c,"BARONY_ACH_THESEUS_LEGACY"); break; } } if( !PORTAL_NOTSECRET ) secretlevel = (secretlevel==FALSE); // toggle level lists return; } } } }
void actGoldBag(Entity *my) { int i; if( my->flags[INVISIBLE] ) { if( multiplayer!=CLIENT ) { node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity->sprite == 245 ) // boulder.vox return; } my->flags[INVISIBLE] = FALSE; serverUpdateEntityFlag(my,INVISIBLE); if( !strcmp(map.name,"Sokoban") ) { for( i=0; i<MAXPLAYERS; i++ ) steamAchievementClient(i,"BARONY_ACH_PUZZLE_MASTER"); } } else { return; } } GOLDBAG_AMBIENCE--; if( GOLDBAG_AMBIENCE<=0 ) { GOLDBAG_AMBIENCE = TICKS_PER_SECOND*30; playSoundEntityLocal( my, 149, 16 ); } // pick up gold if( multiplayer!=CLIENT ) { for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { if (players[i] && players[i]->entity) playSoundEntity(players[i]->entity, 242+rand()%4, 64 ); stats[i]->GOLD += GOLDBAG_AMOUNT; if( i!=0 ) { if( multiplayer==SERVER ) { // send the client info on the gold it picked up strcpy((char *)net_packet->data,"GOLD"); SDLNet_Write32(stats[i]->GOLD,&net_packet->data[4]); net_packet->address.host = net_clients[i-1].host; net_packet->address.port = net_clients[i-1].port; net_packet->len = 8; sendPacketSafe(net_sock, -1, net_packet, i-1); } } // message for item pickup if( GOLDBAG_AMOUNT==1 ) messagePlayer(i,language[483]); else messagePlayer(i,language[484],GOLDBAG_AMOUNT); // remove gold entity list_RemoveNode(my->mynode); return; } } } } else { my->flags[NOUPDATE] = TRUE; } }
void actItem(Entity* my) { Item* item; int i; if ( multiplayer == CLIENT ) { my->flags[NOUPDATE] = true; if ( ITEM_LIFE == 0 ) { Entity* tempEntity = uidToEntity(clientplayer); if ( tempEntity ) { if ( entityInsideEntity(my, tempEntity) ) { my->parent = tempEntity->getUID(); } else { node_t* node; for ( node = map.creatures->first; node != nullptr; node = node->next ) { Entity* entity = (Entity*)node->element; if ( entity->behavior == &actPlayer || entity->behavior == &actMonster ) { if ( entityInsideEntity(my, entity) ) { my->parent = entity->getUID(); break; } } } } } else { node_t* node; for ( node = map.creatures->first; node != nullptr; node = node->next ) { Entity* entity = (Entity*)node->element; if ( entity->behavior == &actPlayer || entity->behavior == &actMonster ) { if ( entityInsideEntity(my, entity) ) { my->parent = entity->getUID(); break; } } } } } // request entity update (check if I've been deleted) if ( ticks % (TICKS_PER_SECOND * 5) == my->getUID() % (TICKS_PER_SECOND * 5) ) { strcpy((char*)net_packet->data, "ENTE"); net_packet->data[4] = clientnum; SDLNet_Write32(my->getUID(), &net_packet->data[5]); net_packet->address.host = net_server.host; net_packet->address.port = net_server.port; net_packet->len = 9; sendPacketSafe(net_sock, -1, net_packet, 0); } } else { // select appropriate model my->skill[2] = -5; if ( my->itemSokobanReward != 1 ) { my->flags[INVISIBLE] = false; } item = newItemFromEntity(my); my->sprite = itemModel(item); free(item); } //if( ITEM_LIFE==0 ) // playSoundEntityLocal( my, 149, 64 ); ITEM_LIFE++; /*ITEM_AMBIENCE++; if( ITEM_AMBIENCE>=TICKS_PER_SECOND*30 ) { ITEM_AMBIENCE=0; playSoundEntityLocal( my, 149, 64 ); }*/ // pick up item if (multiplayer != CLIENT) { if ( my->isInteractWithMonster() ) { Entity* monsterInteracting = uidToEntity(my->interactedByMonster); if ( monsterInteracting ) { if ( my->skill[10] >= 0 && my->skill[10] < NUMITEMS ) { if ( items[my->skill[10]].category == Category::FOOD && monsterInteracting->getMonsterTypeFromSprite() != SLIME ) { monsterInteracting->monsterConsumeFoodEntity(my, monsterInteracting->getStats()); } else { monsterInteracting->monsterAddNearbyItemToInventory(monsterInteracting->getStats(), 24, 9, my); } } my->clearMonsterInteract(); return; } my->clearMonsterInteract(); } for ( i = 0; i < MAXPLAYERS; i++) { if ((i == 0 && selectedEntity == my) || (client_selected[i] == my)) { if (inrange[i]) { if (players[i] != nullptr && players[i]->entity != nullptr) { playSoundEntity( players[i]->entity, 35 + rand() % 3, 64 ); } Item* item2 = newItemFromEntity(my); if ( players[i] && players[i]->entity ) { if ( my->itemStolen == 1 && item2 && (static_cast<Uint32>(item2->ownerUid) == players[i]->entity->getUID()) ) { steamAchievementClient(i, "BARONY_ACH_REPOSSESSION"); } } //messagePlayer(i, "old owner: %d", item2->ownerUid); if (item2) { item = itemPickup(i, item2); if (item) { if (i == 0) { free(item2); } int oldcount = item->count; item->count = 1; messagePlayer(i, language[504], item->description()); item->count = oldcount; if (i != 0) { free(item); } my->removeLightField(); list_RemoveNode(my->mynode); return; } } } } } } if ( my->itemNotMoving ) { switch ( my->sprite ) { case 610: case 611: case 612: case 613: my->spawnAmbientParticles(80, my->sprite - 4, 10 + rand() % 40, 1.0, false); if ( !my->light ) { my->light = lightSphereShadow(my->x / 16, my->y / 16, 3, 192); } break; default: break; } if ( multiplayer == CLIENT ) { // let the client process some more gravity and make sure it isn't stopping early at an awkward angle. if ( my->itemNotMovingClient == 1 ) { return; } } else { return; } } // gravity bool onground = false; if ( my->z < 7.5 - models[my->sprite]->sizey * .25 ) { // fall // chakram and shuriken lie flat, needs to use sprites for client if ( my->sprite == 567 || my->sprite == 569 ) { // todo: adjust falling rates for thrown items if need be ITEM_VELZ += 0.04; my->z += ITEM_VELZ; my->roll += 0.08; } else { ITEM_VELZ += 0.04; my->z += ITEM_VELZ; my->roll += 0.04; } } else { if ( my->x >= 0 && my->y >= 0 && my->x < map.width << 4 && my->y < map.height << 4 ) { if ( map.tiles[(int)(my->y / 16)*MAPLAYERS + (int)(my->x / 16)*MAPLAYERS * map.height] || (my->sprite >= 610 && my->sprite <= 613) ) { // land ITEM_VELZ *= -.7; if ( ITEM_VELZ > -.35 ) { // chakram and shuriken lie flat, needs to use sprites for client if ( my->sprite == 567 || my->sprite == 569 ) { my->roll = PI; my->pitch = 0; if ( my->sprite == 569 ) { my->z = 8.5 - models[my->sprite]->sizey * .25; } else { my->z = 8.75 - models[my->sprite]->sizey * .25; } } else { my->roll = PI / 2.0; my->z = 7.5 - models[my->sprite]->sizey * .25; } ITEM_VELZ = 0; onground = true; } else { onground = true; my->z = 7.5 - models[my->sprite]->sizey * .25 - .0001; } } else { // fall ITEM_VELZ += 0.04; my->z += ITEM_VELZ; my->roll += 0.04; } } else { // fall ITEM_VELZ += 0.04; my->z += ITEM_VELZ; my->roll += 0.04; } } // falling out of the map if ( my->z > 128 ) { if ( ITEM_TYPE == ARTIFACT_MACE && my->parent != 0 ) { steamAchievementEntity(uidToEntity(my->parent), "BARONY_ACH_STFU"); } list_RemoveNode(my->mynode); return; } // don't perform unneeded computations on items that have basically no velocity double groundheight; if ( my->sprite == 569 ) { groundheight = 8.5 - models[my->sprite]->sizey * .25; } else if ( my->sprite == 567 ) { groundheight = 8.75 - models[my->sprite]->sizey * .25; } else { groundheight = 7.5 - models[my->sprite]->sizey * .25; } if ( onground && my->z > groundheight - .0001 && my->z < groundheight + .0001 && fabs(ITEM_VELX) < 0.02 && fabs(ITEM_VELY) < 0.02 ) { my->itemNotMoving = 1; my->flags[UPDATENEEDED] = false; if ( multiplayer != CLIENT ) { serverUpdateEntitySkill(my, 18); //update itemNotMoving flag } else { my->itemNotMovingClient = 1; } return; } // horizontal motion if ( ITEM_NOCOLLISION ) { double newx = my->x + ITEM_VELX; double newy = my->y + ITEM_VELY; if ( !checkObstacle( newx, newy, my, NULL ) ) { my->x = newx; my->y = newy; my->yaw += sqrt( ITEM_VELX * ITEM_VELX + ITEM_VELY * ITEM_VELY ) * .05; } } else { double result = clipMove(&my->x, &my->y, ITEM_VELX, ITEM_VELY, my); my->yaw += result * .05; if ( result != sqrt( ITEM_VELX * ITEM_VELX + ITEM_VELY * ITEM_VELY ) ) { if ( !hit.side ) { ITEM_VELX *= -.5; ITEM_VELY *= -.5; } else if ( hit.side == HORIZONTAL ) { ITEM_VELX *= -.5; } else { ITEM_VELY *= -.5; } } } ITEM_VELX = ITEM_VELX * .925; ITEM_VELY = ITEM_VELY * .925; }