void slimeDie(Entity *my) { Entity *entity; int c = 0; for( c=0; c<5; c++ ) { Entity *gib = spawnGib(my); serverSpawnGibForClient(gib); } if (spawn_blood) { int x, y; x = std::min<unsigned int>(std::max<int>(0,my->x/16),map.width-1); y = std::min<unsigned int>(std::max<int>(0,my->y/16),map.height-1); if( map.tiles[y*MAPLAYERS+x*MAPLAYERS*map.height] ) { if( !checkObstacle(my->x,my->y,my,NULL) ) { if( my->sprite == 210 ) entity = newEntity(212,1,map.entities); else entity = newEntity(214,1,map.entities); entity->x = my->x; entity->y = my->y; entity->z = 7.4+(rand()%20)/100.f; entity->parent = my->uid; entity->sizex = 2; entity->sizey = 2; entity->yaw = (rand()%360)*PI/180.0; entity->flags[UPDATENEEDED] = TRUE; entity->flags[PASSABLE] = TRUE; } } } playSoundEntity(my, 69, 64); list_RemoveNode(my->mynode); return; }
void readNextDistance(I2cBusConnection* i2cBusConnection) { if (!readNextDistanceFlag) { return; } readNextDistanceFlag = false; unsigned int distance = getSRF02DistanceEndRanging(i2cBusConnection, SONAR_INDEX); delaymSec(1); startSRF02Ranging(i2cBusConnection, SONAR_INDEX); distances[(unsigned int) distanceIndex] = distance; /* appendDec(getDebugOutputStreamLogger(), distance); append(getDebugOutputStreamLogger(), '.'); */ // Manage index of history distanceIndex++; if (distanceIndex > ROBOT_SONAR_DETECTOR_DEVICE_HISTORY_SIZE) { distanceIndex = 0; } if (checkObstacle()) { // for the main LOOP obstacle = true; } }
RobotPosition PledgeAlgorithm::getNextPosition(const RobotPosition p_pos) { int x = (int) meterToCm(p_pos.point.x); int y = (int) meterToCm(p_pos.point.y); float theta = p_pos.theta; bool obstacle = false; bool leftSideObstacle = false; RobotPosition newPosition; if(turn == 0) { if(!obstacle) { newPosition = calculateNewPosition(x, y, theta); return newPosition; } else { obstacleFound = true; while(obstacle) // evtl sackgasse { theta -= M_PI/2; turn--; obstacle = checkObstacle(x, y, theta); } newPosition = calculateNewPosition(x, y, theta); return newPosition; } } if(turn != 0) { leftSideObstacle = checkLeftSideObstacle(x, y, theta); if(leftSideObstacle) { newPosition = calculateNewPosition(x, y, theta); return newPosition; } else { theta += M_PI/2; //drehung nach links? turn++; newPosition = calculateNewPosition(x, y, theta); return newPosition; } } }
void gnomeDie(Entity *my) { node_t *node, *nextnode; int c; for( c=0; c<6; c++ ) { Entity *entity = spawnGib(my); if( entity ) serverSpawnGibForClient(entity); } if (spawn_blood) { int x, y; x = std::min<unsigned int>(std::max<int>(0,my->x/16),map.width-1); y = std::min<unsigned int>(std::max<int>(0,my->y/16),map.height-1); if( map.tiles[y*MAPLAYERS+x*MAPLAYERS*map.height] ) { if( !checkObstacle(my->x,my->y,my,NULL) ) { Entity *entity = newEntity(160,1,map.entities); entity->x = my->x; entity->y = my->y; entity->z = 7.4+(rand()%20)/100.f; entity->parent = my->uid; entity->sizex = 2; entity->sizey = 2; entity->yaw = (rand()%360)*PI/180.0; entity->flags[UPDATENEEDED] = TRUE; entity->flags[PASSABLE] = TRUE; } } } int i = 0; for( node=my->children.first; node!=NULL; node=nextnode ) { nextnode = node->next; if( node->element != NULL && i >= 2 ) { Entity *entity=(Entity *)node->element; if( entity->light != NULL ) list_RemoveNode(entity->light->node); entity->light = NULL; list_RemoveNode(entity->mynode); } list_RemoveNode(node); i++; } playSoundEntity(my,225+rand()%4,128); list_RemoveNode(my->mynode); return; }
void actBoulderTrap(Entity *my) { int x, y; int c; BOULDERTRAP_AMBIENCE--; if( BOULDERTRAP_AMBIENCE<=0 ) { BOULDERTRAP_AMBIENCE = TICKS_PER_SECOND*30; playSoundEntity( my, 149, 64 ); } if( !my->skill[28] ) return; // received on signal if( my->skill[28] == 2) { if( !BOULDERTRAP_FIRED ) { playSoundEntity(my, 150, 128); for( c=0; c<MAXPLAYERS; c++ ) playSoundPlayer(c, 150, 64); BOULDERTRAP_FIRED = 1; for( c=0; c<4; c++ ) { switch( c ) { case 0: x = 16; y = 0; break; case 1: x = 0; y = 16; break; case 2: x = -16; y = 0; break; case 3: x = 0; y = -16; break; } x = ((int)(x+my->x))>>4; y = ((int)(y+my->y))>>4; if( x>=0 && y>=0 && x<map.width && y<map.height ) { if( !map.tiles[OBSTACLELAYER+y*MAPLAYERS+x*MAPLAYERS*map.height] ) { Entity *entity = newEntity(245, 1, map.entities); // boulder entity->parent = my->uid; entity->x = (x<<4)+8; entity->y = (y<<4)+8; entity->z = -64; entity->yaw = c*(PI/2.f); entity->sizex = 7; entity->sizey = 7; if( checkObstacle( entity->x+cos(entity->yaw)*16, entity->y+sin(entity->yaw)*16, entity, NULL ) ) { entity->yaw += PI*(rand()%2)-PI/2; if( entity->yaw >= PI*2 ) entity->yaw -= PI*2; else if( entity->yaw < 0 ) entity->yaw += PI*2; } entity->behavior = &actBoulder; entity->flags[UPDATENEEDED] = TRUE; entity->flags[PASSABLE] = TRUE; } } } } }
void initShopkeeper(Entity *my, stat_t *myStats) { int c; node_t *node; my->sprite = 217; //my->flags[GENIUS]=TRUE; my->flags[UPDATENEEDED]=TRUE; my->flags[BLOCKSIGHT]=TRUE; my->flags[INVISIBLE]=FALSE; if( multiplayer!=CLIENT ) { MONSTER_SPOTSND = -1; MONSTER_SPOTVAR = 1; MONSTER_IDLESND = -1; MONSTER_IDLEVAR = 1; } if( multiplayer!=CLIENT && !MONSTER_INIT ) { if( myStats ) { for( c=0; c<std::max(NUMPROFICIENCIES,NUMEFFECTS); c++ ) { if( c<NUMPROFICIENCIES ) myStats->PROFICIENCIES[c]=0; if( c<NUMEFFECTS ) { myStats->EFFECTS[c]=FALSE; myStats->EFFECTS_TIMERS[c]=0; } } } int x, y; MONSTER_SHOPXS = my->x/16; MONSTER_SHOPXE = my->x/16; MONSTER_SHOPYS = my->y/16; MONSTER_SHOPYE = my->y/16; for( x=my->x; x>=0; x-=16 ) { if( !checkObstacle(x,my->y,my,NULL) ) MONSTER_SHOPXS = x; else break; } for( x=my->x; x<map.width<<4; x+=16 ) { if( !checkObstacle(x,my->y,my,NULL) ) MONSTER_SHOPXE = x; else break; } for( y=my->y; y>=0; y-=16 ) { if( !checkObstacle(my->x,y,my,NULL) ) MONSTER_SHOPYS = y; else break; } for( y=my->y; y<map.height<<4; y+=16 ) { if( !checkObstacle(my->x,y,my,NULL) ) MONSTER_SHOPYE = y; else break; } for( x=MONSTER_SHOPXS-16; x<=MONSTER_SHOPXE+16; x+=16 ) { for( y=MONSTER_SHOPYS-16; y<=MONSTER_SHOPYE+16; y+=16 ) { if( x/16>=0 && x/16<map.width && y/16>=0 && y/16<map.height ) shoparea[y/16+(x/16)*map.height] = TRUE; } } myStats->sex = MALE; myStats->appearance = rand(); strcpy(myStats->name,language[158+rand()%26]); myStats->inventory.first = NULL; myStats->inventory.last = NULL; myStats->HP = 300; myStats->MAXHP = 300; myStats->MP = 200; myStats->MAXMP = 200; myStats->OLDHP = myStats->HP; myStats->STR = 10; myStats->DEX = 4; myStats->CON = 10; myStats->INT = 7; myStats->PER = 7; myStats->CHR = 3+rand()%4; myStats->EXP = 0; myStats->LVL = 10; myStats->GOLD = 300+rand()%200; myStats->HUNGER = 900; if( !myStats->leader_uid ) myStats->leader_uid = 0; myStats->FOLLOWERS.first=NULL; myStats->FOLLOWERS.last=NULL; myStats->PROFICIENCIES[PRO_MAGIC]=50; myStats->PROFICIENCIES[PRO_SPELLCASTING]=50; myStats->PROFICIENCIES[PRO_TRADING]=75; myStats->PROFICIENCIES[PRO_APPRAISAL]=75; myStats->helmet = NULL; myStats->breastplate = NULL; myStats->gloves = NULL; myStats->shoes = NULL; myStats->shield = NULL; myStats->weapon = NULL; myStats->cloak = NULL; myStats->amulet = NULL; myStats->ring = NULL; myStats->mask = NULL; myStats->weapon = newItem(SPELLBOOK_MAGICMISSILE,EXCELLENT,0,1,0,FALSE,NULL); if( rand()%20==0 ) { myStats->EFFECTS[EFF_ASLEEP] = TRUE; myStats->EFFECTS_TIMERS[EFF_ASLEEP] = 1800+rand()%3600; } // give shopkeeper items MONSTER_STORETYPE = rand()%9; if( MONSTER_STORETYPE==8 ) MONSTER_STORETYPE++; int numitems = 10+rand()%5; switch( MONSTER_STORETYPE ) { case 0: // arms & armor store for( c=0; c<numitems; c++ ) { if( rand()%2 ) { newItem( static_cast<ItemType>(rand()%20), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%4, rand(), FALSE, &myStats->inventory ); } else { int i=rand()%21; if( i<18 ) newItem( static_cast<ItemType>(GLOVES+i), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%4, rand(), FALSE, &myStats->inventory ); else newItem( static_cast<ItemType>(GLOVES+i+4), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%6, rand(), FALSE, &myStats->inventory ); } } break; case 1: // hat store for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(HAT_PHRYGIAN+rand()%7), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%6, rand(), FALSE, &myStats->inventory ); } break; case 2: // jewelry store for( c=0; c<numitems; c++ ) { switch( rand()%3 ) { case 0: newItem( static_cast<ItemType>(AMULET_SEXCHANGE+rand()%6), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%2, rand(), FALSE, &myStats->inventory ); break; case 1: newItem( static_cast<ItemType>(RING_ADORNMENT+rand()%12), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%2, rand(), FALSE, &myStats->inventory ); break; case 2: newItem( static_cast<ItemType>(GEM_GARNET+rand()%16), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%2, rand(), FALSE, &myStats->inventory ); break; } } break; case 3: // bookstore for( c=0; c<numitems; c++ ) { switch( rand()%3 ) { case 0: newItem( static_cast<ItemType>(SPELLBOOK_FORCEBOLT+rand()%22), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%2, rand(), TRUE, &myStats->inventory ); break; case 1: newItem( static_cast<ItemType>(SCROLL_MAIL+rand()%14), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%2, rand(), TRUE, &myStats->inventory ); break; case 2: newItem( READABLE_BOOK, static_cast<Status>(WORN+rand()%3), 0, 1+rand()%3, rand(), FALSE, &myStats->inventory ); break; } } break; case 4: // apothecary for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(POTION_WATER+rand()%15), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%5, rand(), TRUE, &myStats->inventory ); } break; case 5: // staff shop for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(MAGICSTAFF_LIGHT+rand()%10), static_cast<Status>(WORN+rand()%3), 0, 1, 1, TRUE, &myStats->inventory ); } break; case 6: // food store for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(FOOD_BREAD+rand()%7), static_cast<Status>(SERVICABLE+rand()%2), 0, 1+rand()%3, rand(), FALSE, &myStats->inventory ); } break; case 7: // hardware store for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(TOOL_PICKAXE+rand()%11), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%3, rand(), FALSE, &myStats->inventory ); } break; case 8: // lighting store for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(TOOL_TORCH+rand()%2), EXCELLENT, 0, 1, 7, FALSE, &myStats->inventory ); } break; case 9: // general store for( c=0; c<numitems; c++ ) { newItem( static_cast<ItemType>(rand()%(NUMITEMS-(NUMITEMS-SPELL_ITEM))), static_cast<Status>(WORN+rand()%3), 0, 1+rand()%3, rand(), FALSE, &myStats->inventory ); } break; } } // torso Entity *entity = newEntity(218, 0, map.entities); entity->sizex = 4; entity->sizey = 4; entity->skill[2] = my->uid; entity->flags[PASSABLE]=TRUE; entity->flags[NOUPDATE]=TRUE; entity->flags[USERFLAG2]=my->flags[USERFLAG2]; entity->focalx = limbs[SHOPKEEPER][1][0]; // 0 entity->focaly = limbs[SHOPKEEPER][1][1]; // 0 entity->focalz = limbs[SHOPKEEPER][1][2]; // 0 entity->behavior=&actShopkeeperLimb; entity->parent=my->uid; node = list_AddNodeLast(&my->children); node->element = entity; node->deconstructor = &emptyDeconstructor; node->size = sizeof(Entity *); // right leg entity = newEntity(222, 0, map.entities); entity->sizex = 4; entity->sizey = 4; entity->skill[2] = my->uid; entity->flags[PASSABLE]=TRUE; entity->flags[NOUPDATE]=TRUE; entity->flags[USERFLAG2]=my->flags[USERFLAG2]; entity->focalx = limbs[SHOPKEEPER][2][0]; // 0 entity->focaly = limbs[SHOPKEEPER][2][1]; // 0 entity->focalz = limbs[SHOPKEEPER][2][2]; // 2 entity->behavior=&actShopkeeperLimb; entity->parent=my->uid; node = list_AddNodeLast(&my->children); node->element = entity; node->deconstructor = &emptyDeconstructor; node->size = sizeof(Entity *); // left leg entity = newEntity(221, 0, map.entities); entity->sizex = 4; entity->sizey = 4; entity->skill[2] = my->uid; entity->flags[PASSABLE]=TRUE; entity->flags[NOUPDATE]=TRUE; entity->flags[USERFLAG2]=my->flags[USERFLAG2]; entity->focalx = limbs[SHOPKEEPER][3][0]; // 0 entity->focaly = limbs[SHOPKEEPER][3][1]; // 0 entity->focalz = limbs[SHOPKEEPER][3][2]; // 2 entity->behavior=&actShopkeeperLimb; entity->parent=my->uid; node = list_AddNodeLast(&my->children); node->element = entity; node->deconstructor = &emptyDeconstructor; node->size = sizeof(Entity *); // right arm entity = newEntity(220, 0, map.entities); entity->sizex = 4; entity->sizey = 4; entity->skill[2] = my->uid; entity->flags[PASSABLE]=TRUE; entity->flags[NOUPDATE]=TRUE; entity->flags[USERFLAG2]=my->flags[USERFLAG2]; entity->focalx = limbs[SHOPKEEPER][4][0]; // 0 entity->focaly = limbs[SHOPKEEPER][4][1]; // 0 entity->focalz = limbs[SHOPKEEPER][4][2]; // 1.5 entity->behavior=&actShopkeeperLimb; entity->parent=my->uid; node = list_AddNodeLast(&my->children); node->element = entity; node->deconstructor = &emptyDeconstructor; node->size = sizeof(Entity *); // left arm entity = newEntity(219, 0, map.entities); entity->sizex = 4; entity->sizey = 4; entity->skill[2] = my->uid; entity->flags[PASSABLE]=TRUE; entity->flags[NOUPDATE]=TRUE; entity->flags[USERFLAG2]=my->flags[USERFLAG2]; entity->focalx = limbs[SHOPKEEPER][5][0]; // 0 entity->focaly = limbs[SHOPKEEPER][5][1]; // 0 entity->focalz = limbs[SHOPKEEPER][5][2]; // 1.5 entity->behavior=&actShopkeeperLimb; entity->parent=my->uid; node = list_AddNodeLast(&my->children); node->element = entity; node->deconstructor = &emptyDeconstructor; node->size = sizeof(Entity *); }
Node* AIManager::astar(Vector3f end, Vector3f begin) { bool firstGo = true; Node* start = new Node(begin); Node* goal = new Node(end); Node* current; std::vector<Node*> openlist; std::vector<Node*> closelist; Vector3f goalvf = end; openlist.push_back(start); std::make_heap(openlist.begin(), openlist.end()); while(!openlist.empty()) { current = openlist.front(); std::pop_heap(openlist.begin(), openlist.end()); openlist.pop_back(); if(isGoal(current, goal)) { return current; } // getSuccessors(current, openlist, closelist, end); //If adjacent position is not obstacle and not on closed //add adjacent positions to list Node* temp = new Node; bool valid = true; //if(!Overlay::isObstacle(current->_x+STEP, current->_y, current->_z)) if(!checkObstacle(Vector3f(current->_x+STEP, current->_y, current->_z))) { temp->_x = current->_x+STEP; temp->_z = current->_z; for(unsigned int i = 0; i < closelist.size() && valid; ++i) { if(temp->isSamePosition(closelist[i])) valid = false; } if(valid) { temp->_g = current->_g+GSCORE; temp->_h = calculateHn(Vector3f(float(temp->_x), float(temp->_y), float(temp->_z)), goalvf); temp->calculateFn(); temp->setParent(current); openlist.push_back(temp); std::push_heap(openlist.begin(), openlist.end()); } } //if(!Overlay::isObstacle(current->_x-STEP, current->_y, current->_z)) if(!checkObstacle(Vector3f(current->_x-STEP, current->_y, current->_z))) { temp->_x = current->_x-STEP; temp->_z = current->_z; for(unsigned int i = 0; i < closelist.size() && valid; ++i) { if(temp->isSamePosition(closelist[i])) valid = false; } if(valid) { temp->_g = current->_g+GSCORE; temp->_h = calculateHn(Vector3f(float(temp->_x), float(temp->_y), float(temp->_z)), goalvf); temp->calculateFn(); temp->setParent(current); openlist.push_back(temp); std::push_heap(openlist.begin(), openlist.end()); } valid = true; } //if(!Overlay::isObstacle(current->_x, current->_y, current->_z+STEP)) if(!checkObstacle(Vector3f(current->_x, current->_y, current->_z+STEP))) { temp->_x = current->_x; temp->_z = current->_z+STEP; for(unsigned int i = 0; i < closelist.size() && valid; ++i) { if(temp->isSamePosition(closelist[i])) valid = false; } if(valid) { temp->_g = current->_g+GSCORE; temp->_h = calculateHn(Vector3f(float(temp->_x), float(temp->_y), float(temp->_z)), goalvf); temp->calculateFn(); temp->setParent(current); openlist.push_back(temp); std::push_heap(openlist.begin(), openlist.end()); } valid = true; } //if(!Overlay::isObstacle(current->_x, current->_y, current->_z-STEP)) if(!checkObstacle(Vector3f(current->_x, current->_y, current->_z-STEP))) { temp->_x = current->_x; temp->_z = current->_z-STEP; for(unsigned int i = 0; i < closelist.size() && valid; ++i) { if(temp->isSamePosition(closelist[i])) valid = false; } if(valid) { temp->_g = current->_g+GSCORE; temp->_h = calculateHn(Vector3f(float(temp->_x), float(temp->_y), float(temp->_z)), goalvf); temp->calculateFn(); temp->setParent(current); openlist.push_back(temp); std::push_heap(openlist.begin(), openlist.end()); } valid = true; } if(firstGo && !openlist.empty()) { std::make_heap(openlist.begin(), openlist.end()); firstGo = false; } closelist.push_back(current); return current; } return NULL; }
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; }