// ZZZ: If not already in predictive mode, save off partial game-state for later restoration.
static void
enter_predictive_mode()
{
	if(sPredictedTicks == 0)
	{
		for(short i = 0; i < dynamic_world->player_count; i++)
		{
			sSavedPlayerData[i] = *get_player_data(i);
			if(sSavedPlayerData[i].monster_index != NONE)
			{
				sSavedPlayerMonsterData[i] = *get_monster_data(sSavedPlayerData[i].monster_index);
				if(sSavedPlayerMonsterData[i].object_index != NONE)
				{
					sSavedPlayerObjectData[i] = *get_object_data(sSavedPlayerMonsterData[i].object_index);
					sSavedPlayerObjectNextObject[i] = sSavedPlayerObjectData[i].next_object;
					if(sSavedPlayerObjectData[i].parasitic_object != NONE)
						sSavedPlayerParasiticObjectData[i] = *get_object_data(sSavedPlayerObjectData[i].parasitic_object);
				}
			}
		}
		
		// Sanity checking
		sSavedTickCount = dynamic_world->tick_count;
		sSavedRandomSeed = get_random_seed();
	}
}
Exemple #2
0
static void m2_swipe_nearby_items(short player_index)
{
	object_data *object;
	object_data *player_object;
	player_data *player= get_player_data(player_index);
	short next_object;
	polygon_data *polygon;
	short *neighbor_indexes;
	short i;

	player_object= get_object_data(get_monster_data(player->monster_index)->object_index);

	polygon= get_polygon_data(player_object->polygon);
	neighbor_indexes= get_map_indexes(polygon->first_neighbor_index, polygon->neighbor_count);
	
	// Skip this step if neighbor indexes were not found
	if (!neighbor_indexes) return;

	for (i=0;i<polygon->neighbor_count;++i)
	{	
		
		polygon_data *neighboring_polygon= get_polygon_data(*neighbor_indexes++);
	
		if (POLYGON_IS_DETACHED(neighboring_polygon))
			continue;
	
		next_object= neighboring_polygon->first_object;

		while(next_object != NONE)
		{
			object= get_object_data(next_object);
			if (GET_OBJECT_OWNER(object)==_object_is_item && !OBJECT_IS_INVISIBLE(object)) 
			{
				if (guess_distance2d((world_point2d *) &player->location, (world_point2d *) &object->location)<=MAXIMUM_ARM_REACH)
				{
					world_distance radius, height;
					
					get_monster_dimensions(player->monster_index, &radius, &height);
	
					if (object->location.z >= player->location.z - MAXIMUM_ARM_REACH && object->location.z <= player->location.z + height &&
						test_item_retrieval(player_object->polygon, &player_object->location, &object->location))
					{
						if(get_item(player_index, next_object))
						{
							/* Start the search again.. */
							next_object= neighboring_polygon->first_object;
							continue;
						}
					}
				}
			}
			
			next_object= object->next_object;
		}
	
	}
}
static int Lua_Monster_Get_Polygon(lua_State *L)
{
    monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
    object_data *object = get_object_data(monster->object_index);
    Lua_Polygon::Push(L, object->polygon);
    return 1;
}
static int Lua_Monster_Get_Facing(lua_State *L)
{
    monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
    object_data *object = get_object_data(monster->object_index);
    lua_pushnumber(L, (double) object->facing * AngleConvert);
    return 1;
}
static int Lua_Effect_Get_Facing(lua_State* L)
{
	effect_data* effect = get_effect_data(Lua_Effect::Index(L, 1));
	object_data* object = get_object_data(effect->object_index);
	lua_pushnumber(L, (double) object->facing * AngleConvert);
	return 1;
}
static int Lua_Effect_Get_Polygon(lua_State* L)
{
	effect_data* effect = get_effect_data(Lua_Effect::Index(L, 1));
	object_data* object = get_object_data(effect->object_index);
	Lua_Polygon::Push(L, object->polygon);
	return 1;
}
static int Lua_Effect_Get_Z(lua_State* L)
{
	effect_data* effect = get_effect_data(Lua_Effect::Index(L, 1));
	object_data* object = get_object_data(effect->object_index);
	lua_pushnumber(L, (double) object->location.z / WORLD_ONE);
	return 1;
}
int Lua_Effect_Position(lua_State* L)
{
	if (!lua_isnumber(L, 2) || !lua_isnumber(L, 3) || !lua_isnumber(L, 4))
		return luaL_error(L, "position: incorrect argument type");

	short polygon_index = 0;
	if (lua_isnumber(L, 5))
	{
		polygon_index = static_cast<int>(lua_tonumber(L, 5));
		if (!Lua_Polygon::Valid(polygon_index))
			return luaL_error(L, "position: invalid polygon index");
	}
	else if (Lua_Polygon::Is(L, 5))
	{
		polygon_index = Lua_Polygon::Index(L, 5);
	}
	else
		return luaL_error(L, "position: incorrect argument type");

	effect_data* effect = get_effect_data(Lua_Effect::Index(L, 1));
	object_data *object = get_object_data(effect->object_index);
	object->location.x = static_cast<int>(lua_tonumber(L, 2) * WORLD_ONE);
	object->location.y = static_cast<int>(lua_tonumber(L, 3) * WORLD_ONE);
	object->location.z = static_cast<int>(lua_tonumber(L, 4) * WORLD_ONE);

	if (polygon_index != object->polygon)
	{
		remove_object_from_polygon_object_list(effect->object_index);
		add_object_to_polygon_object_list(effect->object_index, polygon_index);
	}

	return 0;
	
}
static bool Lua_Scenery_Valid(int32 index)
{
	if (index < 0 || index >= MAXIMUM_OBJECTS_PER_MAP)
		return false;

	object_data *object = GetMemberWithBounds(objects, index, MAXIMUM_OBJECTS_PER_MAP);
	if (SLOT_IS_USED(object))
	{
		if (GET_OBJECT_OWNER(object) == _object_is_scenery) 
			return true;
		else if (GET_OBJECT_OWNER(object) == _object_is_normal)
		{
			// check to make sure it's not a player's legs or torso
			for (int player_index = 0; player_index < dynamic_world->player_count; player_index++)
			{
				player_data *player = get_player_data(player_index);
				monster_data *monster = get_monster_data(player->monster_index);
				if (monster->object_index == index) 
					return false;
				else
				{
					object_data *object = get_object_data(monster->object_index);
					if (object->parasitic_object == index)
						return false;
				}
			}

			return true;
		}
	}

	return false;
}
static int Lua_Monster_Get_Z(lua_State *L)
{
    monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
    object_data *object = get_object_data(monster->object_index);
    lua_pushnumber(L, (double) object->location.z / WORLD_ONE);
    return 1;
}
static int Lua_Monster_Get_Visible(lua_State *L)
{
    monster_data *monster = get_monster_data(Lua_Monster::Index(L, 1));
    object_data *object = get_object_data(monster->object_index);
    lua_pushboolean(L, OBJECT_IS_VISIBLE(object));
    return 1;
}
Exemple #12
0
/** Create an object
    \verbatim gl('create', class, property, value, ...) \endverbatim
 **/
void cmex_create(int nlhs, mxArray *plhs[], /**< {properties} */
				 int nrhs, const mxArray *prhs[]) /**< (class, property1, value1, property2, value2, ..., propertyN, valueN) */
{
	CLASS *oclass;
	OBJECT *obj;
	CLASSNAME classname;
	unsigned int num_properties = (nrhs-1)/2;

	/* check return value */
	if (nlhs>1)
		output_error("create only returns one struct");
	/* check class name */
	else if (!mxIsChar(prhs[0]))
		output_error("class name (arg 1) must be a string");

	/* get class name */
	else if (mxGetString(prhs[0],classname,sizeof(classname)))
		output_error("unable to read class name (arg 1)");

	/* check the number of properties */
	else if (num_properties!=(nrhs/2))
		output_error("an object property value is missing");

	/* create object */
	else if ((oclass=class_get_class_from_classname(classname))==NULL)
		output_error("class '%s' is not registered", classname);

	/* create the object */
	else if (oclass->create(&obj,NULL)==FAILED)
		output_error("unable to create object of class %s", classname);

	/* copy properties */
	else
	{
		unsigned int i;
		for (i=0; i<num_properties; i++)
		{
			char name[256];
			char value[1024];
			unsigned int n=i*2+1;
			const mxArray *p[] = {prhs[n],prhs[n+1]};
			if (!mxIsChar(p[0]))
				output_error("property name (arg %d) must be a string", n);
			else if (mxGetString(p[0],name,sizeof(name)))
				output_error("property name (arg %d) couldn't be read", n);
			else if (mxIsChar(p[1]) && mxGetString(p[1],value,sizeof(value)))
				output_error("property %s (arg %d) value couldn't be read", name, n);
			else if (mxIsDouble(p[1]) && sprintf(value,"%lg",*(double*)mxGetPr(p[1]))<1)
				output_error("property %s (arg %d) value couldn't be converted from double", name, n);
			else if (mxIsComplex(p[1]) && sprintf(value,"%lg%+lgi",*(double*)mxGetPr(p[1]),*(double*)mxGetPi(p[1]))<1)
				output_error("property %s (arg %d) value couldn't be converted from complex", name, n);
			else if (object_set_value_by_name(obj,name,value)==0)
				output_error("property %s (arg %d) couldn't be set to '%s'", name, n, value);
			else if (nlhs>0 && (plhs[0]=get_object_data(obj))==NULL)
				output_error("couldn't get object data for %s", name);
		}
	}
}
static int set_object_facing(lua_State *L)
{
	if (!lua_isnumber(L, 2))
		return luaL_error(L, "facing: incorrect argument type");

	object_data *object = get_object_data(T::Index(L, 1));
	object->facing = static_cast<int>(lua_tonumber(L, 2) / AngleConvert);
	return 0;
}
static int Lua_Scenery_Set_Solid(lua_State *L)
{
	if (!lua_isboolean(L, 2))
		return luaL_error(L, "solid: incorrect argument type");

	object_data *object = get_object_data(Lua_Scenery::Index(L, 1));
	SET_OBJECT_SOLIDITY(object, lua_toboolean(L, 2));
	return 0;
}
static int Lua_Scenery_Get_Damaged(lua_State *L)
{
	object_data *object = get_object_data(Lua_Scenery::Index(L, 1));

	// if it made it this far (past valid() check),
	// it's either scenery or normal
	lua_pushboolean(L, GET_OBJECT_OWNER(object) == _object_is_normal);
	return 1;
}
int Lua_Monster_Move_By_Path(lua_State *L)
{
    int monster_index = Lua_Monster::Index(L, 1);
    int polygon_index = 0;
    if (lua_isnumber(L, 2))
    {
        polygon_index = static_cast<int>(lua_tonumber(L, 2));
        if (!Lua_Polygon::Valid(polygon_index))
            return luaL_error(L, "move_by_path: invalid polygon index");
    }
    else if (Lua_Polygon::Is(L, 2))
    {
        polygon_index = Lua_Polygon::Index(L, 2);
    }
    else
        return luaL_error(L, "move_by_path: incorrect argument type");

    monster_data *monster = get_monster_data(monster_index);
    if (MONSTER_IS_PLAYER(monster))
        return luaL_error(L, "move_by_path: monster is player");

    monster_definition *definition = get_monster_definition_external(monster->type);
    object_data *object = get_object_data(monster->object_index);
    monster_pathfinding_data path;
    world_point2d destination;

    if (!MONSTER_IS_ACTIVE(monster))
        activate_monster(monster_index);

    if (monster->path != NONE)
    {
        delete_path(monster->path);
        monster->path = NONE;
    }

    SET_MONSTER_NEEDS_PATH_STATUS(monster, false);
    path.definition = definition;
    path.monster = monster;
    path.cross_zone_boundaries = true;

    destination = get_polygon_data(polygon_index)->center;

    monster->path = new_path((world_point2d *) &object->location, object->polygon, &destination, polygon_index, 3 * definition->radius, monster_pathfinding_cost_function, &path);
    if (monster->path == NONE)
    {
        if (monster->action != _monster_is_being_hit || MONSTER_IS_DYING(monster))
        {
            set_monster_action(monster_index, _monster_is_stationary);
        }
        set_monster_mode(monster_index, _monster_unlocked, NONE);
        return 0;
    }

    advance_monster_path(monster_index);
    return 0;
}
static int Lua_Effect_Set_Facing(lua_State* L)
{
	if (!lua_isnumber(L, 2))
		return luaL_error(L, "facing: incorrect argument type");

	effect_data* effect = get_effect_data(Lua_Effect::Index(L, 1));
	object_data* object = get_object_data(effect->object_index);
	object->facing = static_cast<int>(lua_tonumber(L, 2) / AngleConvert);
	return 0;
}
int Lua_Item_Delete(lua_State* L)
{
	object_data* object = get_object_data(Lua_Item::Index(L, 1));
	int16 item_type = object->permutation;

	remove_map_object(Lua_Item::Index(L, 1));
	if (L_Get_Proper_Item_Accounting(L))
	{
		object_was_just_destroyed(_object_is_item, item_type);
	}
	return 0;
}
Exemple #19
0
/* every other field in the player structure should be valid when this call is made */
void initialize_player_physics_variables(
	short player_index)
{
	struct player_data *player= get_player_data(player_index);
	struct monster_data *monster= get_monster_data(player->monster_index);
	struct object_data *object= get_object_data(monster->object_index);
	struct physics_variables *variables= &player->variables;
	struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, 0);

//#ifdef DEBUG
	obj_set(*variables, 0x80);
//#endif
	
	variables->head_direction= 0;
	variables->adjusted_yaw= variables->direction= INTEGER_TO_FIXED(object->facing);
	variables->adjusted_pitch= variables->elevation= 0;
	variables->angular_velocity= variables->vertical_angular_velocity= 0;
	variables->velocity= 0, variables->perpendicular_velocity= 0;
	variables->position.x= WORLD_TO_FIXED(object->location.x);
	variables->position.y= WORLD_TO_FIXED(object->location.y);
	variables->position.z= WORLD_TO_FIXED(object->location.z);
	variables->last_position= variables->position;
	variables->last_direction= variables->direction;
	/* .floor_height, .ceiling_height and .media_height will be calculated by instantiate, below */

	variables->external_angular_velocity= 0;
	variables->external_velocity.i= variables->external_velocity.j= variables->external_velocity.k= 0;
	variables->actual_height= constants->height;
	
	variables->step_phase= 0;
	variables->step_amplitude= 0;
	
	variables->action= _player_stationary;
	variables->old_flags= variables->flags= 0; /* not recentering, not above ground, not below ground (i.e., on floor) */

	/* setup shadow variables in player_data structure */
	instantiate_physics_variables(get_physics_constants_for_model(static_world->physics_model, 0),
		&player->variables, player_index, true, true);

#ifdef DIVERGENCE_CHECK
	if (!saved_point_iterations)
	{
		saved_points= new world_point3d[SAVED_POINT_COUNT];
		saved_thetas= new angle[SAVED_POINT_COUNT];
	}
	saved_point_count= 0;
	saved_point_iterations+= 1;
	saved_divergence_warning= false;
#endif
}
Exemple #20
0
static bool get_item(short player_index, short object_index) 
{
	object_data *object = get_object_data(object_index);	
	bool success;

	assert(GET_OBJECT_OWNER(object)==_object_is_item);
	
	success = try_and_add_player_item(player_index, object->permutation);
	if (success)
	{
		/* remove it */
		remove_map_object(object_index);
	}
	
	return success;
}
    std::shared_ptr<MeshFormatObject> MeshFormat::spawn_object(const StringIntern& s){
        MeshFormatObjectData* d = &get_object_data(s);
        if(!d){
            std::cout<<s<<" was not found\n";
            return nullptr;
        }
        std::shared_ptr<MeshFormatObject> o(new MeshFormatObject(d,&file));

        if(d->materials.size())
        o->material=get_material(d->materials[0]);

        o->parent = &*spawned_nodes[d->parent];
        if(!o->parent)o->parent=this;

        return o;
    }
Exemple #22
0
/* false means donÕt fire this (itÕs in a floor or ceiling or outside of the map), otherwise
	the monster that was intersected first (or NONE) is returned in target_index */
bool preflight_projectile(
	world_point3d *origin,
	short origin_polygon_index,
	world_point3d *destination,
	angle delta_theta,
	short type,
	short owner,
	short owner_type,
	short *obstruction_index)
{
	bool legal_projectile= false;
	struct projectile_definition *definition= get_projectile_definition(type);
	
	(void) (delta_theta);
	
	/* will be used when we truly preflight projectiles */
	(void) (owner_type);
	
	if (origin_polygon_index!=NONE)
	{
		world_distance dx= destination->x-origin->x, dy= destination->y-origin->y;
		angle elevation= arctangent(isqrt(dx*dx + dy*dy), destination->z-origin->z);
		
		if (elevation<MAXIMUM_PROJECTILE_ELEVATION || elevation>FULL_CIRCLE-MAXIMUM_PROJECTILE_ELEVATION)
		{
			struct polygon_data *origin_polygon= get_polygon_data(origin_polygon_index);
			
			// LP note: "penetrates media boundary" means "hit media surface and continue";
			// it will act like "penetrates_media" here
			// Added idiot-proofing to media data
			media_data *media = get_media_data(origin_polygon->media_index);
			if (origin->z>origin_polygon->floor_height && origin->z<origin_polygon->ceiling_height &&
				(origin_polygon->media_index==NONE || definition->flags&(_penetrates_media) || (media ? origin->z>media->height : true)))
			{
				/* make sure it hits something */
				uint16 flags= translate_projectile(type, origin, origin_polygon_index, destination, (short *) NULL, owner, obstruction_index, 0, true, NONE);
				
				*obstruction_index= (flags&_projectile_hit_monster) ? get_object_data(*obstruction_index)->permutation : NONE;
				legal_projectile= true;
			}
		}
	}
	
	return legal_projectile;
}
Exemple #23
0
static boolean line_is_within_range(
	short monster_index,
	short line_index,
	world_distance range)
{
	world_point3d monster_origin= get_object_data(get_monster_data(monster_index)->object_index)->location;
	world_point3d line_origin;
	world_distance radius, height;
	world_distance dx, dy, dz;
	
	calculate_line_midpoint(line_index, &line_origin);
	get_monster_dimensions(monster_index, &radius, &height);
	monster_origin.z+= height>>1;
	
	dx= monster_origin.x-line_origin.x;
	dy= monster_origin.y-line_origin.y;
	dz= 2*(monster_origin.z-line_origin.z); /* dz is weighted */
	
	return isqrt(dx*dx + dy*dy + dz*dz)<range ? TRUE : FALSE;
}
void cause_polygon_damage(
	short polygon_index,
	short monster_index)
{
	struct polygon_data *polygon= get_polygon_data(polygon_index);
	struct monster_data *monster= get_monster_data(monster_index);
	struct object_data *object= get_object_data(monster->object_index);
    
    short polygon_type = polygon->type;
    // apply damage from flooded platforms
    if (polygon->type == _polygon_is_platform)
	{
		struct platform_data *platform= get_platform_data(polygon->permutation);
		if (platform && PLATFORM_IS_FLOODED(platform))
		{
			short adj_index = find_flooding_polygon(polygon_index);
			if (adj_index != NONE)
			{
				struct polygon_data *adj_polygon = get_polygon_data(adj_index);
				polygon_type = adj_polygon->type;
			}
		}
	}


// #if 0
	if ((polygon_type==_polygon_is_minor_ouch && !(dynamic_world->tick_count&MINOR_OUCH_FREQUENCY) && object->location.z==polygon->floor_height) ||
		(polygon_type==_polygon_is_major_ouch && !(dynamic_world->tick_count&MAJOR_OUCH_FREQUENCY)))
	{
		struct damage_definition damage;
		
		damage.flags= _alien_damage;
		damage.type= polygon_type==_polygon_is_minor_ouch ? _damage_polygon : _damage_major_polygon;
		damage.base= polygon_type==_polygon_is_minor_ouch ? MINOR_OUCH_DAMAGE : MAJOR_OUCH_DAMAGE;
		damage.random= 0;
		damage.scale= FIXED_ONE;
		
		damage_monster(monster_index, NONE, NONE, (world_point3d *) NULL, &damage, NONE);
	}
// #endif
}
Exemple #25
0
void update_player_physics_variables(
	short player_index,
	uint32 action_flags,
	bool predictive)
{
	struct player_data *player= get_player_data(player_index);
	struct physics_variables *variables= &player->variables;
	struct physics_constants *constants= get_physics_constants_for_model(static_world->physics_model, action_flags);

	physics_update(constants, variables, player, action_flags);
	instantiate_physics_variables(constants, variables, player_index, false, !predictive);

#ifdef DIVERGENCE_CHECK
	if (saved_point_count<SAVED_POINT_COUNT)
	{
		struct object_data *object= get_object_data(get_monster_data(player->monster_index)->object_index);
		world_point3d p= object->location;
		world_point3d *q= saved_points+saved_point_count;
		angle *facing= saved_thetas+saved_point_count;
		
		if (saved_point_iterations==1)
		{
			saved_points[saved_point_count]= p;
			*facing= object->facing;
		}
		else
		{
			if (p.x!=q->x||p.y!=q->y||p.z!=q->z||*facing!=object->facing&&!saved_divergence_warning)
			{
				dprintf("divergence @ tick %d: (%d,%d,%d,%d)!=(%d,%d,%d,%d)", saved_point_count,
					q->x, q->y, q->z, *facing, p.x, p.y, p.z, object->facing);
				saved_divergence_warning= true;
			}
		}
		
		saved_point_count+= 1;
	}
#endif
}
static int Lua_Monster_Set_Visible(lua_State *L) {
    int monster_index = Lua_Monster::Index(L, 1);
    monster_data *monster = get_monster_data(monster_index);
    object_data *object = get_object_data(monster->object_index);
    int invisible = !lua_toboolean(L, 2);
    if(monster->action == _monster_is_teleporting_out) return 0;
    if(MONSTER_IS_ACTIVE(monster) || monster->vitality >= 0) {
        // Cool stuff happens if you just set an active
        // monster to invisible.  What we should do instead of
        // the below is expose teleports_out_when_deactivated
        /*if(invisible) {
          monster->flags |= (uint16)_monster_teleports_out_when_deactivated;
          deactivate_monster(monster_index);
          }*/
        return luaL_error(L, "visible: monster already activated");
    }
    else {
        // No real possibility of messing stuff up here.
        SET_OBJECT_INVISIBILITY(object, invisible);
    }
    return 0;
}
Exemple #27
0
void trigger_nearby_items(short polygon_index)
{
	polygon_index = flood_map(polygon_index, INT32_MAX, item_trigger_cost_function, _breadth_first, nullptr);
	while(polygon_index != NONE)
	{
		object_data *object;

		for(auto object_index = get_polygon_data(polygon_index)->first_object; object_index != NONE; object_index = object->next_object)
		{
			object = get_object_data(object_index);
			switch (GET_OBJECT_OWNER(object))
			{
				case _object_is_item:
					if (OBJECT_IS_INVISIBLE(object) && object->permutation!=NONE)
					{
						teleport_object_in(object_index);
					}
					break;
			}
		}
		
		polygon_index= flood_map(NONE, INT32_MAX, item_trigger_cost_function, _breadth_first, nullptr);
	}
}
static int get_object_y(lua_State *L)
{
	object_data *object = get_object_data(T::Index(L, 1));
	lua_pushnumber(L, (double) object->location.y / WORLD_ONE);
	return 1;
}
static int get_object_type(lua_State *L)
{
	object_data *object = get_object_data(T::Index(L, 1));
	TT::Push(L, object->permutation);
	return 1;
}
static int get_object_polygon(lua_State *L)
{
	object_data *object = get_object_data(T::Index(L, 1));
	Lua_Polygon::Push(L, object->polygon);
	return 1;
}