short new_projectile( world_point3d *origin, short polygon_index, world_point3d *_vector, angle delta_theta, /* ±¶theta is added (in a circle) to the angle before firing */ short type, short owner_index, short owner_type, short intended_target_index, /* can be NONE */ _fixed damage_scale) { struct projectile_definition *definition; struct projectile_data *projectile; short projectile_index; type= adjust_projectile_type(origin, polygon_index, type, owner_index, owner_type, intended_target_index, damage_scale); definition= get_projectile_definition(type); for (projectile_index= 0, projectile= projectiles; projectile_index<MAXIMUM_PROJECTILES_PER_MAP; ++projectile_index, ++projectile) { if (SLOT_IS_FREE(projectile)) { angle facing, elevation; short object_index; struct object_data *object; facing= arctangent(_vector->x, _vector->y); elevation= arctangent(isqrt(_vector->x*_vector->x+_vector->y*_vector->y), _vector->z); if (delta_theta) { if (!(definition->flags&_no_horizontal_error)) facing= normalize_angle(facing+global_random()%(2*delta_theta)-delta_theta); if (!(definition->flags&_no_vertical_error)) elevation= (definition->flags&_positive_vertical_error) ? normalize_angle(elevation+global_random()%delta_theta) : normalize_angle(elevation+global_random()%(2*delta_theta)-delta_theta); } object_index= new_map_object3d(origin, polygon_index, definition->collection==NONE ? NONE : BUILD_DESCRIPTOR(definition->collection, definition->shape), facing); if (object_index!=NONE) { object= get_object_data(object_index); projectile->type= (definition->flags&_alien_projectile) ? (alien_projectile_override==NONE ? type : alien_projectile_override) : (human_projectile_override==NONE ? type : human_projectile_override); projectile->object_index= object_index; projectile->owner_index= owner_index; projectile->target_index= intended_target_index; projectile->owner_type= owner_type; projectile->flags= 0; projectile->gravity= 0; projectile->ticks_since_last_contrail= projectile->contrail_count= 0; projectile->elevation= elevation; projectile->distance_travelled= 0; projectile->damage_scale= damage_scale; MARK_SLOT_AS_USED(projectile); SET_OBJECT_OWNER(object, _object_is_projectile); object->sound_pitch= definition->sound_pitch; L_Call_Projectile_Created(projectile_index); } else { projectile_index= NONE; } break; } } if (projectile_index==MAXIMUM_PROJECTILES_PER_MAP) projectile_index= NONE; return projectile_index; }
short new_item(struct object_location *location,short type) { short object_index; item_definition *definition= get_item_definition(type); // LP change: added idiot-proofing if (!definition) return false; bool add_item = true; assert(sizeof(item_definitions)/sizeof(struct item_definition)==NUMBER_OF_DEFINED_ITEMS); /* Do NOT add items that are network-only in a single player game, and vice-versa */ if (dynamic_world->player_count>1) { if (definition->invalid_environments & _environment_network) add_item = false; if (get_item_kind(type)==_ball && !current_game_has_balls()) add_item = false; } else { if (definition->invalid_environments & _environment_single_player) add_item= false; } if (add_item) { /* add the object to the map */ object_index= new_map_object(location, definition->base_shape); if (object_index!=NONE) { object_data *object= get_object_data(object_index); // LP addition: using the facing direction as a flag in the "unanimated" case: // will be initially zero, but will become nonzero when initialized, // so that the shape randomization will be done only once. SET_OBJECT_OWNER(object, _object_is_item); object->permutation= type; if ((location->flags&_map_object_is_network_only) && dynamic_world->player_count<=1) { SET_OBJECT_INVISIBILITY(object, true); object->permutation= NONE; } else if ((get_item_kind(type) == _ball) && !static_world->ball_in_play) { static_world->ball_in_play = true; SoundManager::instance()->PlayLocalSound(_snd_got_ball); } /* let PLACEMENT.C keep track of how many there are */ object_was_just_added(_object_is_item, type); // and let Lua know too L_Call_Item_Created(object_index); } } else object_index = NONE; return object_index; }