void minotaurDie(Entity* my) { int c; for ( c = 0; c < 5; c++ ) { Entity* gib = spawnGib(my); serverSpawnGibForClient(gib); } my->spawnBlood(); for ( c = 0; c < MAXPLAYERS; c++ ) { playSoundPlayer(c, 114, 128); } my->removeMonsterDeathNodes(); list_RemoveNode(my->mynode); return; }
void actShopkeeperLimb(Entity *my) { int i; Entity *parent = NULL; if( (parent=uidToEntity(my->skill[2]))==NULL ) { list_RemoveNode(my->mynode); return; } if( multiplayer!=CLIENT ) { for( i=0; i<MAXPLAYERS; i++ ) { if( inrange[i] ) { if( i==0 && selectedEntity==my ) { parent->skill[13] = i+1; } else if( client_selected[i]==my ) { parent->skill[13] = i+1; } } } } return; }
void actRightHandMagic(Entity *my) { if (intro == TRUE) { my->flags[INVISIBLE] = TRUE; return; } //Initialize if( !HANDMAGIC_INIT ) { HANDMAGIC_INIT=1; my->focalz = -1.5; } if( players[clientnum]==NULL ) { magicRightHand=NULL; list_RemoveNode(my->mynode); return; } my->x = 8; my->y = 3; my->z = (camera.z *.5 - players[clientnum]->z) + 7; my->z -= 4; my->yaw = HANDMAGIC_YAW - camera_shakex2; double defaultpitch = (0-6.f) / PI; my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f; my->roll = HANDMAGIC_ROLL; //Sprite bool noGloves=FALSE; if( stats[clientnum].gloves == NULL ) { noGloves=TRUE; } else { if( stats[clientnum].gloves->type == GLOVES || stats[clientnum].gloves->type == GLOVES_DEXTERITY ) { my->sprite = 132 + stats[clientnum].sex; } else if( stats[clientnum].gloves->type == BRACERS || stats[clientnum].gloves->type == BRACERS_CONSTITUTION ) { my->sprite = 323 + stats[clientnum].sex; } else if( stats[clientnum].gloves->type == GAUNTLETS || stats[clientnum].gloves->type == GAUNTLETS_STRENGTH ) { my->sprite = 140 + stats[clientnum].sex; } else { noGloves = TRUE; } } if( noGloves ) { if( stats[clientnum].appearance/6==0 ) { if( stats[clientnum].sex==FEMALE ) { my->sprite = 121; } else { my->sprite = 109; } } else if( stats[clientnum].appearance/6==1 ) { if( stats[clientnum].sex==FEMALE ) { my->sprite = 350; } else { my->sprite = 337; } } else { if( stats[clientnum].sex==FEMALE ) { my->sprite = 376; } else { my->sprite = 363; } } } bool wearingring = FALSE; //Select model if (stats[clientnum].ring != NULL) if (stats[clientnum].ring->type == RING_INVISIBILITY) wearingring = TRUE; if (stats[clientnum].cloak != NULL) if (stats[clientnum].cloak->type == CLOAK_INVISIBILITY) wearingring = TRUE; if (players[clientnum]->skill[3] == 1 || stats[clientnum].EFFECTS[EFF_INVISIBLE] == TRUE || wearingring ) { // debug cam or player invisible my->flags[INVISIBLE] = TRUE; } if (cast_animation.active) { switch (cast_animation.stage) { case CIRCLE: if (ticks%5==0) { //messagePlayer(0, "Pingas!"); Entity *entity = spawnGib(my); entity->flags[INVISIBLE] = FALSE; entity->flags[SPRITE] = TRUE; entity->flags[NOUPDATE] = TRUE; entity->flags[UPDATENEEDED] = FALSE; entity->flags[OVERDRAW] = TRUE; entity->flags[BRIGHT] = TRUE; //entity->sizex = 1; //MAKE 'EM SMALL PLEASE! //entity->sizey = 1; entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE! entity->scaley = 0.25f; entity->scalez = 0.25f; entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead? entity->yaw = ((rand()%6)*60)*PI/180.0; entity->pitch = (rand()%360)*PI/180.0; entity->roll = (rand()%360)*PI/180.0; entity->vel_x = cos(entity->yaw)*.1; entity->vel_y = sin(entity->yaw)*.1; entity->vel_z = -.15; entity->fskill[3] = 0.01; } break; case THROW: break; default: break; } } //Final position code. if( players[clientnum] == NULL ) return; //double defaultpitch = PI / 8.f; //double defaultpitch = 0; //double defaultpitch = PI / (0-4.f); defaultpitch = (0-6.f) / PI; //my->x = 6 + HUDWEAPON_MOVEX; my->x = 8; my->x += cast_animation.lefthand_movex; //my->y = 3 + HUDWEAPON_MOVEY; my->y = 3; my->y -= cast_animation.lefthand_movey; //my->z = (camera.z*.5-players[clientnum]->z)+7+HUDWEAPON_MOVEZ; my->z = (camera.z *.5 - players[clientnum]->z) + 7; my->z -= 4; my->yaw = HANDMAGIC_YAW - camera_shakex2; my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f; my->roll = HANDMAGIC_ROLL; }
void actLeftHandMagic(Entity *my) { //int c = 0; if (intro == TRUE) { my->flags[INVISIBLE] = TRUE; return; } //Initialize if (!HANDMAGIC_INIT) { HANDMAGIC_INIT = 1; HANDMAGIC_TESTVAR = 0; my->focalz = -1.5; } if( players[clientnum]==NULL ) { magicLeftHand = NULL; spellcastingAnimationManager_deactivate(&cast_animation); list_RemoveNode(my->mynode); return; } //Set the initial values. (For the particle spray) my->x = 8; my->y = -3; my->z = (camera.z *.5 - players[clientnum]->z) + 7; my->z -= 4; my->yaw = HANDMAGIC_YAW - camera_shakex2; double defaultpitch = (0-6.f) / PI; my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f; my->roll = HANDMAGIC_ROLL; //Sprite bool noGloves=FALSE; if( stats[clientnum].gloves == NULL ) { noGloves=TRUE; } else { if( stats[clientnum].gloves->type == GLOVES || stats[clientnum].gloves->type == GLOVES_DEXTERITY ) { my->sprite = 136 + stats[clientnum].sex; } else if( stats[clientnum].gloves->type == BRACERS || stats[clientnum].gloves->type == BRACERS_CONSTITUTION ) { my->sprite = 327 + stats[clientnum].sex; } else if( stats[clientnum].gloves->type == GAUNTLETS || stats[clientnum].gloves->type == GAUNTLETS_STRENGTH ) { my->sprite = 144 + stats[clientnum].sex; } else { noGloves = TRUE; } } if( noGloves ) { if( stats[clientnum].appearance/6==0 ) { if( stats[clientnum].sex==FEMALE ) { my->sprite = 122; } else { my->sprite = 110; } } else if( stats[clientnum].appearance/6==1 ) { if( stats[clientnum].sex==FEMALE ) { my->sprite = 351; } else { my->sprite = 338; } } else { if( stats[clientnum].sex==FEMALE ) { my->sprite = 377; } else { my->sprite = 364; } } } bool wearingring = FALSE; //Select model if (stats[clientnum].ring != NULL) if (stats[clientnum].ring->type == RING_INVISIBILITY) wearingring = TRUE; if (stats[clientnum].cloak != NULL) if (stats[clientnum].cloak->type == CLOAK_INVISIBILITY) wearingring = TRUE; if (players[clientnum]->skill[3] == 1 || stats[clientnum].EFFECTS[EFF_INVISIBLE] == TRUE || wearingring ) { // debug cam or player invisible my->flags[INVISIBLE] = TRUE; } if (cast_animation.active) { switch (cast_animation.stage) { case CIRCLE: if(ticks%5==0) { Entity *entity = spawnGib(my); entity->flags[INVISIBLE] = FALSE; entity->flags[SPRITE] = TRUE; entity->flags[NOUPDATE] = TRUE; entity->flags[UPDATENEEDED] = FALSE; entity->flags[OVERDRAW] = TRUE; entity->flags[BRIGHT] = TRUE; entity->scalex = 0.25f; //MAKE 'EM SMALL PLEASE! entity->scaley = 0.25f; entity->scalez = 0.25f; entity->sprite = 16; //TODO: Originally. 22. 16 -- spark sprite instead? entity->yaw = ((rand()%6)*60)*PI/180.0; entity->pitch = (rand()%360)*PI/180.0; entity->roll = (rand()%360)*PI/180.0; entity->vel_x = cos(entity->yaw)*.1; entity->vel_y = sin(entity->yaw)*.1; entity->vel_z = -.15; entity->fskill[3] = 0.01; } cast_animation.consume_timer--; if (cast_animation.consume_timer < 0 && cast_animation.mana_left > 0) { //Time to consume mana and reset the ticker! cast_animation.consume_timer = cast_animation.consume_interval; if (multiplayer == SINGLE) { players[clientnum]->drainMP(1); } cast_animation.mana_left--; } cast_animation.lefthand_angle += HANDMAGIC_CIRCLE_SPEED; cast_animation.lefthand_movex = cos(cast_animation.lefthand_angle) * HANDMAGIC_CIRCLE_RADIUS; cast_animation.lefthand_movey = sin(cast_animation.lefthand_angle) * HANDMAGIC_CIRCLE_RADIUS; if (cast_animation.lefthand_angle >= 2 * PI) { //Completed one loop. cast_animation.lefthand_angle = 0; cast_animation.circle_count++; if (cast_animation.circle_count >= cast_animation.times_to_circle) //Finished circling. Time to move on! cast_animation.stage++; } break; case THROW: //messagePlayer(clientnum, "IN THROW"); //TODO: Throw animation! Or something. cast_animation.stage++; break; default: //messagePlayer(clientnum, "DEFAULT CASE"); spellcastingAnimationManager_completeSpell(&cast_animation); break; } } //Final position code. if( players[clientnum] == NULL ) return; //double defaultpitch = PI / 8.f; //double defaultpitch = 0; //double defaultpitch = PI / (0-4.f); defaultpitch = (0-6.f) / PI; //my->x = 6 + HUDWEAPON_MOVEX; my->x += cast_animation.lefthand_movex; //my->y = 3 + HUDWEAPON_MOVEY; my->y = -3; my->y += cast_animation.lefthand_movey; //my->z = (camera.z*.5-players[clientnum]->z)+7+HUDWEAPON_MOVEZ; my->z = (camera.z *.5 - players[clientnum]->z) + 7; my->z -= 4; my->yaw = HANDMAGIC_YAW - camera_shakex2; my->pitch = defaultpitch + HANDMAGIC_PITCH - camera_shakey2 / 200.f; my->roll = HANDMAGIC_ROLL; }
void actMinotaurCeilingBuster(Entity* my) { double x, y; // levitate particles int u = std::min<unsigned int>(std::max<int>(0, my->x / 16), map.width - 1); int v = std::min<unsigned int>(std::max<int>(0, my->y / 16), map.height - 1); if ( !map.tiles[v * MAPLAYERS + u * MAPLAYERS * map.height] ) { int c; for ( c = 0; c < 2; c++ ) { Entity* entity = newEntity(171, 1, map.entities, nullptr); //Particle entity. entity->x = my->x - 8 + rand() % 17; entity->y = my->y - 8 + rand() % 17; entity->z = 10 + rand() % 3; entity->scalex = 0.7; entity->scaley = 0.7; entity->scalez = 0.7; entity->sizex = 1; entity->sizey = 1; entity->yaw = (rand() % 360) * PI / 180.f; entity->flags[PASSABLE] = true; entity->flags[BRIGHT] = true; entity->flags[NOUPDATE] = true; entity->flags[UNCLICKABLE] = true; entity->behavior = &actMagicParticle; if ( multiplayer != CLIENT ) { entity_uids--; } entity->setUID(-3); } } // bust ceilings for ( x = my->x - my->sizex - 1; x <= my->x + my->sizex + 1; x += 1 ) { for ( y = my->y - my->sizey - 1; y <= my->y + my->sizey + 1; y += 1 ) { if ( x >= 0 && y >= 0 && x < map.width << 4 && y < map.height << 4 ) { int index = (MAPLAYERS - 1) + ((int)floor(y / 16)) * MAPLAYERS + ((int)floor(x / 16)) * MAPLAYERS * map.height; if ( map.tiles[index] ) { if ( my->monsterAttack == 0 ) { if ( multiplayer != CLIENT ) { my->attack(MONSTER_POSE_MELEE_WINDUP2, 0, nullptr); } return; } else if ( my->monsterAttack == MONSTER_POSE_MELEE_WINDUP2 ) { return; } map.tiles[index] = 0; if ( multiplayer != CLIENT ) { playSoundEntity(my, 67, 128); //MONSTER_ATTACK = 1; Stat* myStats = my->getStats(); if ( myStats ) { // easy hack to stop the minotaur while he breaks stuff myStats->EFFECTS[EFF_PARALYZED] = true; myStats->EFFECTS_TIMERS[EFF_PARALYZED] = 10; } } // spawn several rock particles (NOT items) int c, i = 6 + rand() % 4; for ( c = 0; c < i; c++ ) { Entity *entity = nullptr; if ( multiplayer == SERVER ) { entity = spawnGib(my); } else { entity = spawnGibClient(my->x, my->y, my->z, 5); } if ( entity ) { entity->x = ((int)(my->x / 16)) * 16 + rand() % 16; entity->y = ((int)(my->y / 16)) * 16 + rand() % 16; entity->z = -8; entity->flags[PASSABLE] = true; entity->flags[INVISIBLE] = false; entity->flags[NOUPDATE] = true; entity->flags[UPDATENEEDED] = false; entity->sprite = items[GEM_ROCK].index; entity->yaw = rand() % 360 * PI / 180; entity->pitch = rand() % 360 * PI / 180; entity->roll = rand() % 360 * PI / 180; entity->vel_x = (rand() % 20 - 10) / 10.0; entity->vel_y = (rand() % 20 - 10) / 10.0; entity->vel_z = -.25; entity->fskill[3] = 0.03; } } } node_t* node, *nextnode; std::vector<list_t*> entLists = TileEntityList.getEntitiesWithinRadiusAroundEntity(my, 2); for ( std::vector<list_t*>::iterator it = entLists.begin(); it != entLists.end(); ++it ) { list_t* currentList = *it; for ( node = currentList->first; node != nullptr; node = nextnode ) { nextnode = node->next; Entity* entity = (Entity*)node->element; if ( (int)(x / 16) == (int)(entity->x / 16) && (int)(y / 16) == (int)(entity->y / 16) ) { if ( entity->behavior == &actDoorFrame ) { // spawn several rock items int c, i = 8 + rand() % 4; for ( c = 0; c < i; c++ ) { Entity *entity = nullptr; if ( multiplayer == SERVER ) { entity = spawnGib(my); } else { entity = spawnGibClient(my->x, my->y, my->z, 5); } if ( entity ) { entity->x = ((int)(my->x / 16)) * 16 + rand() % 16; entity->y = ((int)(my->y / 16)) * 16 + rand() % 16; entity->z = -8; entity->flags[PASSABLE] = true; entity->flags[INVISIBLE] = false; entity->flags[NOUPDATE] = true; entity->flags[UPDATENEEDED] = false; entity->sprite = items[GEM_ROCK].index; entity->yaw = rand() % 360 * PI / 180; entity->pitch = rand() % 360 * PI / 180; entity->roll = rand() % 360 * PI / 180; entity->vel_x = (rand() % 20 - 10) / 10.0; entity->vel_y = (rand() % 20 - 10) / 10.0; entity->vel_z = -.25; entity->fskill[3] = 0.03; } } list_RemoveNode(entity->mynode); } else if ( entity->behavior == &actDoor ) { if ( multiplayer != CLIENT ) { entity->skill[4] = 0; // destroy the door } } else if ( entity->behavior == &actGate ) { if ( multiplayer != CLIENT ) { playSoundEntity(entity, 76, 64); list_RemoveNode(entity->mynode); } } else if ( entity->behavior == &actStalagCeiling || entity->behavior == &actStalagFloor || entity->behavior == &actStalagColumn ) { // spawn several rock items int c, i = rand() % 4; for ( c = 0; c < i; ++c ) { //Entity* childEntity = spawnGib(my); Entity *childEntity = nullptr; if ( multiplayer == SERVER ) { childEntity = spawnGib(my); } else { childEntity = spawnGibClient(my->x, my->y, my->z, 5); } if ( entity ) { childEntity->x = ((int)(my->x / 16)) * 16 + rand() % 16; childEntity->y = ((int)(my->y / 16)) * 16 + rand() % 16; childEntity->z = -8; childEntity->flags[PASSABLE] = true; childEntity->flags[INVISIBLE] = false; childEntity->flags[NOUPDATE] = true; childEntity->flags[UPDATENEEDED] = false; childEntity->sprite = items[GEM_ROCK].index; childEntity->yaw = rand() % 360 * PI / 180; childEntity->pitch = rand() % 360 * PI / 180; childEntity->roll = rand() % 360 * PI / 180; childEntity->vel_x = (rand() % 20 - 10) / 10.0; childEntity->vel_y = (rand() % 20 - 10) / 10.0; childEntity->vel_z = -.25; childEntity->fskill[3] = 0.03; } } list_RemoveNode(entity->mynode); } } } } } } } }
void actMinotaurTimer(Entity* my) { node_t* node; MINOTAURTIMER_LIFE++; if (( (currentlevel < 25 && MINOTAURTIMER_LIFE == TICKS_PER_SECOND * 120) || (currentlevel >= 25 && MINOTAURTIMER_LIFE == TICKS_PER_SECOND * 180) ) && rand() % 5 == 0 ) // two minutes if currentlevel < 25, else 3 minutes. { int c; bool spawnedsomebody = false; for ( c = 0; c < 9; c++ ) { Uint32 zapLeaderUid = 0; Entity* monster = summonMonster(HUMAN, my->x, my->y); if ( monster ) { monster->skill[29] = 1; // so we spawn a zap brigadier spawnedsomebody = true; if ( !zapLeaderUid ) { zapLeaderUid = monster->getUID(); } else { Stat* monsterStats = monster->getStats(); monsterStats->leader_uid = zapLeaderUid; } } } if ( spawnedsomebody ) { #ifdef MUSIC fadein_increment = default_fadein_increment * 20; fadeout_increment = default_fadeout_increment * 5; playmusic( sounds[175], false, true, false); #endif for ( c = 0; c < MAXPLAYERS; c++ ) { Uint32 color = SDL_MapRGB(mainsurface->format, 0, 255, 255); if ( stats[c]->type == HUMAN ) { messagePlayerColor(c, color, language[1114], stats[c]->name); } else { messagePlayerColor(c, color, language[3285]); } } } } else if (( (currentlevel < 25 && MINOTAURTIMER_LIFE >= TICKS_PER_SECOND * 150) || (currentlevel >= 25 && MINOTAURTIMER_LIFE >= TICKS_PER_SECOND * 210) ) && !MINOTAURTIMER_ACTIVE ) // two and a half minutes if currentlevel < 25, else 3.5 minutes { Entity* monster = summonMonster(MINOTAUR, my->x, my->y); if ( monster ) { int c; for ( c = 0; c < MAXPLAYERS; c++ ) { playSoundPlayer( c, 107 + rand() % 3, 128 ); Uint32 color = SDL_MapRGB(mainsurface->format, 255, 128, 0); messagePlayerColor(c, color, language[1115]); } MINOTAURTIMER_ACTIVE = MINOTAURTIMER_LIFE; } } if ( MINOTAURTIMER_ACTIVE && MINOTAURTIMER_LIFE >= MINOTAURTIMER_ACTIVE + TICKS_PER_SECOND * 3 ) { int c; for ( c = 0; c < MAXPLAYERS; c++ ) { if ( currentlevel < 25 ) { playSoundPlayer(c, 120 + rand() % 3, 128); Uint32 color = SDL_MapRGB(mainsurface->format, 255, 0, 255); messagePlayerColor(c, color, language[1116]); messagePlayerColor(c, color, language[73]); } else { playSoundPlayer(c, 375, 128); playSoundPlayer(c, 379, 128); messagePlayerColor(c, uint32ColorOrange(*mainsurface), language[1116]); messagePlayerColor(c, uint32ColorOrange(*mainsurface), language[73]); messagePlayerColor(c, uint32ColorBaronyBlue(*mainsurface), language[73]); } } list_RemoveNode(my->mynode); 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 actBoulder(Entity *my) { int i; my->skill[2]=-7; // invokes actEmpty() on clients my->flags[UPDATENEEDED] = TRUE; bool noground=FALSE; int x = std::min<int>(std::max(0,(int)(my->x/16)),map.width); int y = std::min<int>(std::max(0,(int)(my->y/16)),map.height); Uint32 index = y*MAPLAYERS+x*MAPLAYERS*map.height; if( !map.tiles[index] || animatedtiles[map.tiles[index]] ) noground = TRUE; // gravity bool nobounce=TRUE; if( !BOULDER_NOGROUND ) if( noground ) BOULDER_NOGROUND = TRUE; if( my->z < 0 || BOULDER_NOGROUND ) { my->vel_z = std::min(my->vel_z+.1,3.0); nobounce = TRUE; if( my->z >= 128 ) { list_RemoveNode(my->mynode); return; } if( !BOULDER_NOGROUND ) { if( my->z >= -8 && fabs(my->vel_z) > 2 ) { node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity == my ) continue; if( boulderCheckAgainstEntity(my,entity) ) return; } } } } else { if( fabs(my->vel_z) > 1 ) { playSoundEntity(my,182,128); my->vel_z = -(my->vel_z/2); nobounce = TRUE; } else { if( my->vel_z ) playSoundEntity(my,182,128); my->vel_z = 0; nobounce = FALSE; } my->z = 0; } my->z += my->vel_z; if( nobounce ) { if( !my->flags[PASSABLE] ) { my->flags[PASSABLE] = TRUE; if( multiplayer==SERVER ) serverUpdateEntityFlag(my,PASSABLE); } if( !BOULDER_STOPPED ) { my->x += my->vel_x; my->y += my->vel_y; double dist = sqrt(pow(my->vel_x,2)+pow(my->vel_y,2)); my->pitch += dist*.06; my->roll = PI/2; } } else if( !BOULDER_STOPPED ) { if( my->flags[PASSABLE] ) { my->flags[PASSABLE] = FALSE; if( multiplayer==SERVER ) serverUpdateEntityFlag(my,PASSABLE); } // horizontal velocity my->vel_x += cos(my->yaw)*.1; my->vel_y += sin(my->yaw)*.1; if( my->vel_x > 1.5 ) my->vel_x = 1.5; if( my->vel_x < -1.5 ) my->vel_x = -1.5; if( my->vel_y > 1.5 ) my->vel_y = 1.5; if( my->vel_y < -1.5 ) my->vel_y = -1.5; int x = std::min<int>(std::max(0.0,(my->x+cos(my->yaw)*8)/16),map.width-1); int y = std::min<int>(std::max(0.0,(my->y+sin(my->yaw)*8)/16),map.height-1); if( map.tiles[OBSTACLELAYER+y*MAPLAYERS+x*MAPLAYERS*map.height] ) { playSoundEntity(my,181,128); BOULDER_STOPPED = 1; } else { my->x += my->vel_x; my->y += my->vel_y; double dist = sqrt(pow(my->vel_x,2)+pow(my->vel_y,2)); my->pitch += dist*.06; my->roll = PI/2; // crush objects if( dist && !BOULDER_NOGROUND ) { node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity == my ) continue; if( boulderCheckAgainstEntity(my,entity) ) return; } } } } // pushing boulders if( BOULDER_STOPPED ) { if( !BOULDER_ROLLING ) { for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { if( statGetSTR(stats[i])<5 ) { messagePlayer(i,language[456]); } else { if( players[i] ) { playSoundEntity(my, 151, 128); BOULDER_ROLLING=1; my->x = floor(my->x/16)*16+8; my->y = floor(my->y/16)*16+8; BOULDER_DESTX=(int)(my->x/16)*16+8; BOULDER_DESTY=(int)(my->y/16)*16+8; if( (int)(players[i]->x/16) < (int)(my->x/16) ) { BOULDER_ROLLDIR=0; // east } else if( (int)(players[i]->y/16) < (int)(my->y/16) ) { BOULDER_ROLLDIR=1; // south } else if( (int)(players[i]->x/16) > (int)(my->x/16) ) { BOULDER_ROLLDIR=2; // west } else if( (int)(players[i]->y/16) > (int)(my->y/16) ) { BOULDER_ROLLDIR=3; // north } switch( BOULDER_ROLLDIR ) { case 0: BOULDER_DESTX += 16; break; case 1: BOULDER_DESTY += 16; break; case 2: BOULDER_DESTX -= 16; break; case 3: BOULDER_DESTY -= 16; break; } } } } } } } else { switch( BOULDER_ROLLDIR ) { case 0: my->vel_x=1; my->vel_y=0; break; case 1: my->vel_x=0; my->vel_y=1; break; case 2: my->vel_x=-1; my->vel_y=0; break; case 3: my->vel_x=0; my->vel_y=-1; break; } int x = (my->x+my->vel_x*8)/16; int y = (my->y+my->vel_y*8)/16; x = std::min<unsigned int>(std::max(0,x),map.width-1); y = std::min<unsigned int>(std::max(0,y),map.height-1); if( map.tiles[OBSTACLELAYER+y*MAPLAYERS+x*MAPLAYERS*map.height] ) { BOULDER_ROLLING = 0; } else { my->x += my->vel_x; my->y += my->vel_y; double dist = sqrt(pow(my->vel_x,2)+pow(my->vel_y,2)); my->pitch += dist*.06; if( BOULDER_ROLLDIR==0 ) { if( my->x>=BOULDER_DESTX ) { my->x=BOULDER_DESTX; BOULDER_ROLLING=0; } } else if( BOULDER_ROLLDIR==1 ) { if( my->y>=BOULDER_DESTY ) { my->y=BOULDER_DESTY; BOULDER_ROLLING=0; } } else if( BOULDER_ROLLDIR==2 ) { if( my->x<=BOULDER_DESTX ) { my->x=BOULDER_DESTX; BOULDER_ROLLING=0; } } else if( BOULDER_ROLLDIR==3 ) { if( my->y<=BOULDER_DESTY ) { my->y=BOULDER_DESTY; BOULDER_ROLLING=0; } } double dir = my->yaw - BOULDER_ROLLDIR*PI/2; while( dir >= PI ) dir -= PI*2; while( dir < -PI ) dir += PI*2; my->yaw -= dir/16; while( my->yaw < 0 ) my->yaw += 2*PI; while( my->yaw >= 2*PI ) my->yaw -= 2*PI; // crush objects if( dist && !BOULDER_NOGROUND ) { node_t *node; for( node=map.entities->first; node!=NULL; node=node->next ) { Entity *entity = (Entity *)node->element; if( entity == my ) continue; if( boulderCheckAgainstEntity(my,entity) ) return; } } } } } // wrap around angles while( my->pitch >= PI*2 ) my->pitch -= PI*2; while( my->pitch < 0 ) my->pitch += PI*2; while( my->roll >= PI*2 ) my->roll -= PI*2; while( my->roll < 0 ) my->roll += PI*2; // rolling sound if( !BOULDER_STOPPED && (fabs(my->vel_x)>0 || fabs(my->vel_y)>0) ) { BOULDER_AMBIENCE++; if( BOULDER_AMBIENCE>=TICKS_PER_SECOND/3 ) { BOULDER_AMBIENCE=0; playSoundEntity(my, 151, 128); } } }
void castSpellInit(Uint32 caster_uid, spell_t *spell){ Entity *caster = uidToEntity(caster_uid); node_t *node = NULL; if (!caster || !spell) { //Need a spell and caster to cast a spell. return; } if (!spell->elements.first) { return; } if (hudweapon) { if (hudweapon->skill[0] != 0) { //HUDWEAPON_CHOP. return; //Can't cast spells while attacking. } } if (cast_animation.active) { //Already casting spell. return; } int player = -1; int i = 0; for (i = 0; i < numplayers; ++i) { if (caster == players[i]) { player = i; //Set the player. } } if (player > -1) { if( stats[player].defending ) { messagePlayer(player,language[407]); return; } if (spell_isChanneled(spell)) { if (channeledSpells[clientnum], spell) { for (node = channeledSpells[player].first; node; node = node->next) { spell_t *spell_search = (spell_t*)node->element; if (spell_search->ID == spell->ID) { //list_RemoveNode(node); //node = NULL; spell_search->sustain = FALSE; //if (spell->magic_effects) // list_RemoveNode(spell->magic_effects); messagePlayer(player, language[408], spell->name); if (multiplayer == CLIENT) { list_RemoveNode(node); strcpy( (char *)net_packet->data, "UNCH"); net_packet->data[4] = clientnum; SDLNet_Write32(spell->ID, &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); } return; } } } } } int magiccost = 0; //Entity *entity = NULL; //node_t *node = spell->elements->first; stat_t *stat = caster->getStats(); if( !stat ) return; if (stat->EFFECTS[EFF_PARALYZED]) { return; } magiccost = getCostOfSpell(spell); if (magiccost > stat->MP) { if (player >= 0) messagePlayer(player, language[375]); //TODO: Allow overexpending at the cost of extreme danger? (maybe an immensely powerful tree of magic actually likes this -- using your life-force to power spells instead of mana) return; } if (magiccost < 0) { if (player >= 0) messagePlayer(player, "Error: Invalid spell. Mana cost is negative?"); return; } //Hand the torch off to the spell animator. And stuff. Stuff. I mean spell animation handler thingymabobber. fireOffSpellAnimation(&cast_animation, caster->uid, spell); //castSpell(caster, spell); //For now, do this while the spell animations are worked on. }
void statDeconstructor(void *data) { stat_t *stat; if(data != NULL) { stat = (stat_t *)data; if( stat->helmet != NULL ) { if( stat->helmet->node == NULL ) free(stat->helmet); else list_RemoveNode(stat->helmet->node); stat->helmet = NULL; } if( stat->breastplate != NULL ) { if( stat->breastplate->node == NULL ) free(stat->breastplate); else list_RemoveNode(stat->breastplate->node); stat->breastplate = NULL; } if( stat->gloves != NULL ) { if( stat->gloves->node == NULL ) free(stat->gloves); else list_RemoveNode(stat->gloves->node); stat->gloves = NULL; } if( stat->shoes != NULL ) { if( stat->shoes->node == NULL ) free(stat->shoes); else list_RemoveNode(stat->shoes->node); stat->shoes = NULL; } if( stat->shield != NULL ) { if( stat->shield->node == NULL ) free(stat->shield); else list_RemoveNode(stat->shield->node); stat->shield = NULL; } if( stat->weapon != NULL ) { if( stat->weapon->node == NULL ) free(stat->weapon); else list_RemoveNode(stat->weapon->node); stat->weapon = NULL; } if( stat->cloak != NULL ) { if( stat->cloak->node == NULL ) free(stat->cloak); else list_RemoveNode(stat->cloak->node); stat->cloak = NULL; } if( stat->amulet != NULL ) { if( stat->amulet->node == NULL ) free(stat->amulet); else list_RemoveNode(stat->amulet->node); stat->amulet = NULL; } if( stat->ring != NULL ) { if( stat->ring->node == NULL ) free(stat->ring); else list_RemoveNode(stat->ring->node); stat->ring = NULL; } if( stat->mask != NULL ) { if( stat->mask->node == NULL ) free(stat->mask); else list_RemoveNode(stat->mask->node); stat->mask = NULL; } //Free memory for magic effects. node_t *spellnode; spellnode = stat->magic_effects.first; while (spellnode) { node_t *oldnode = spellnode; spellnode = spellnode->next; spell_t *spell = (spell_t*)oldnode->element; spell->magic_effects_node = NULL; } list_FreeAll(&stat->magic_effects); list_FreeAll(&stat->inventory); free(data); } }
void freePlayerEquipment(int x) { if( stats[x].helmet != NULL ) { if( stats[x].helmet->node ) list_RemoveNode(stats[x].helmet->node); else free(stats[x].helmet); stats[x].helmet = NULL; } if( stats[x].breastplate != NULL ) { if( stats[x].breastplate->node ) list_RemoveNode(stats[x].breastplate->node); else free(stats[x].breastplate); stats[x].breastplate = NULL; } if( stats[x].gloves != NULL ) { if( stats[x].gloves->node ) list_RemoveNode(stats[x].gloves->node); else free(stats[x].gloves); stats[x].gloves = NULL; } if( stats[x].shoes != NULL ) { if( stats[x].shoes->node ) list_RemoveNode(stats[x].shoes->node); else free(stats[x].shoes); stats[x].shoes = NULL; } if( stats[x].shield != NULL ) { if( stats[x].shield->node ) list_RemoveNode(stats[x].shield->node); else free(stats[x].shield); stats[x].shield = NULL; } if( stats[x].weapon != NULL ) { if( stats[x].weapon->node ) list_RemoveNode(stats[x].weapon->node); else free(stats[x].weapon); stats[x].weapon = NULL; } if( stats[x].cloak != NULL ) { if( stats[x].cloak->node ) list_RemoveNode(stats[x].cloak->node); else free(stats[x].cloak); stats[x].cloak = NULL; } if( stats[x].amulet != NULL ) { if( stats[x].amulet->node ) list_RemoveNode(stats[x].amulet->node); else free(stats[x].amulet); stats[x].amulet = NULL; } if( stats[x].ring != NULL ) { if( stats[x].ring->node ) list_RemoveNode(stats[x].ring->node); else free(stats[x].ring); stats[x].ring = NULL; } if( stats[x].mask != NULL ) { if( stats[x].mask->node ) list_RemoveNode(stats[x].mask->node); else free(stats[x].mask); stats[x].mask = NULL; } }
void actCampfire(Entity *my) { Entity *entity; int i; // init if( !CAMPFIRE_INIT ) { CAMPFIRE_INIT = 1; CAMPFIRE_HEALTH = MAXPLAYERS; } // crackling sounds if( CAMPFIRE_HEALTH>0 ) { CAMPFIRE_SOUNDTIME--; if( CAMPFIRE_SOUNDTIME <= 0 ) { CAMPFIRE_SOUNDTIME = 480; playSoundEntityLocal( my, 133, 128 ); } // spew flame particles for( i=0; i<3; i++ ) { entity = spawnFlame(my); entity->x += ((rand()%30)-10)/10.f; entity->y += ((rand()%30)-10)/10.f; entity->z -= 1; } entity = spawnFlame(my); entity->z -= 2; // light environment if( !CAMPFIRE_LIGHTING ) { my->light = lightSphereShadow(my->x/16, my->y/16, 6, 160); CAMPFIRE_LIGHTING=1; } CAMPFIRE_FLICKER--; if(CAMPFIRE_FLICKER<=0) { CAMPFIRE_LIGHTING=(CAMPFIRE_LIGHTING==1)+1; if(CAMPFIRE_LIGHTING==1) { if( my->light != NULL ) list_RemoveNode(my->light->node); my->light = lightSphereShadow(my->x/16, my->y/16, 6, 160); } else { if( my->light != NULL ) list_RemoveNode(my->light->node); my->light = lightSphereShadow(my->x/16, my->y/16, 6, 152); } CAMPFIRE_FLICKER=2+rand()%7; } } else { if( my->light ) if( my->light->node ) list_RemoveNode(my->light->node); my->light = NULL; my->flags[BRIGHT] = FALSE; } if( multiplayer != CLIENT ) { // using campfire for(i=0;i<MAXPLAYERS;i++) { if( (i==0 && selectedEntity==my) || (client_selected[i]==my) ) { if(inrange[i]) { if( CAMPFIRE_HEALTH>0 ) { messagePlayer(i,language[457]); CAMPFIRE_HEALTH--; if( CAMPFIRE_HEALTH<=0 ) { serverUpdateEntitySkill(my,3); // extinguish for all clients messagePlayer(i,language[458]); if( my->light ) if( my->light->node ) list_RemoveNode(my->light->node); my->light = NULL; } Item *item = newItem(TOOL_TORCH,WORN,0,1,0,TRUE,NULL); itemPickup(i,item); free(item); } else { messagePlayer(i,language[458]); } } } } } }
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; }