void PROJECTILE::tick()
{
	
	float pt = (server_tick()-start_tick-1)/(float)server_tickspeed();
	float ct = (server_tick()-start_tick)/(float)server_tickspeed();
	vec2 prevpos = get_pos(pt);
	vec2 curpos = get_pos(ct);
	vec2 speed =  curpos - prevpos;

	if (lifespan>-1)
		lifespan--;
	
	vec2 col_pos;
	vec2 new_pos;
	int collide = col_intersect_line(prevpos, curpos, &col_pos, &new_pos);
	CHARACTER *ownerchar;
	if (owner>=0)
		ownerchar = game.get_player_char(owner);
	CHARACTER *targetchr;
	if (freeze)
		targetchr = game.world.intersect_character(prevpos, col_pos, 1.0f, col_pos, ownerchar);
	else
		targetchr = game.world.intersect_character(prevpos, col_pos, 6.0f, col_pos, ownerchar);
	if(targetchr || collide)
	{
		if((flags & PROJECTILE_FLAGS_EXPLODE) && (!targetchr || (targetchr && !freeze)))
		{
			game.create_explosion(col_pos, owner, weapon, false);
			game.create_sound(col_pos, sound_impact);
		}
		else if(targetchr && freeze && targetchr->adminfreeze==false)
			targetchr->freeze(server_tickspeed()*3);
		if (collide && bouncing!=0)
		{
			start_tick=server_tick();
			pos=new_pos;
			if (bouncing==1)
				direction.x=-direction.x;
			else if (bouncing==2)
				direction.y=-direction.y;
			pos+=direction;
		}
		else if (weapon==WEAPON_GUN)
		{
			game.create_damageind(curpos, -atan2(direction.x,direction.y), 10);
			game.world.destroy_entity(this);
		}
		else
			if (!freeze)
				game.world.destroy_entity(this);
	}
	if (lifespan == -1)
	{
		game.world.destroy_entity(this);
	}
}
示例#2
0
CHARACTER *CRATE::get_nearest(int maxdist) {
	CHARACTER *close_characters[MAX_CLIENTS];
	int num = game.world.find_entities(pos, maxdist, (ENTITY**)close_characters, MAX_CLIENTS, NETOBJTYPE_CHARACTER);
	int disti = -1;
	float dist = 10000000.0f;
	for(int i = 0; i < num; i++) {
		if(col_intersect_line(pos, close_characters[i]->pos, 0x0, 0x0)) {
			continue;
		}
		float d = distance(close_characters[i]->pos, pos);
		if(d < dist) {
			disti = i;
			dist = d;
		}
	}
	if(disti == -1) {
		return 0;
	}
		
	return close_characters[disti];
}
void GUN::fire()
{
	CHARACTER *ents[16];
	int num = -1;
	num = game.world.find_entities(pos,RANGE, (ENTITY**)ents, 16, NETOBJTYPE_CHARACTER);
	int id=-1;
	int minlen=0;
	for (int i = 0; i < num; i++)
	{
		CHARACTER *target = ents[i];
		int res;
		vec2 coltile;
		res = col_intersect_line(pos, target->pos,0,0);
		if (!res)
		{
			int len=length(ents[i]->pos - pos);
			if (minlen==0)
			{
				minlen=len;
				id=i;
			}
			else if(minlen>len)
			{
				minlen=len;
				id=i;
			}
		}
	}
	if (id!=-1)
	{
		CHARACTER *target = ents[id];
		vec2 fdir = normalize(target->pos - pos);
		new PLASMA(pos,fdir);
	}
	
}
示例#4
0
void CHARACTER_CORE::tick(bool use_input)
{
	float phys_size = 28.0f;
	triggered_events = 0;

	// get ground state
	bool grounded = false;
	if(col_check_point(pos.x+phys_size/2, pos.y+phys_size/2+5))
		grounded = true;
	if(col_check_point(pos.x-phys_size/2, pos.y+phys_size/2+5))
		grounded = true;
	//platte
	if(col_check_platte(pos.x+phys_size/2, pos.y+phys_size/2+5))
		grounded = true;
	if(col_check_platte(pos.x-phys_size/2, pos.y+phys_size/2+5))
		grounded = true;

	vec2 target_direction = normalize(vec2(input.target_x, input.target_y));

	vel.y += world->tuning.gravity;

	float max_speed = grounded ? world->tuning.ground_control_speed : world->tuning.air_control_speed;
	float accel = grounded ? world->tuning.ground_control_accel : world->tuning.air_control_accel;
	float friction = grounded ? world->tuning.ground_friction : world->tuning.air_friction;

	// handle input
	if(use_input)
	{
		direction = input.direction;

		// setup angle
		float a = 0;
		if(input.target_x == 0)
			a = atan((float)input.target_y);
		else
			a = atan((float)input.target_y/(float)input.target_x);

		if(input.target_x < 0)
			a = a+pi;

		angle = (int)(a*256.0f);

		// handle jump
		if(input.jump)
		{
			if(!(jumped&1))
			{
				if(grounded)
				{
					triggered_events |= COREEVENT_GROUND_JUMP;
					vel.y = -world->tuning.ground_jump_impulse;
					jumped |= 1;
				}
				else if(!(jumped&2))
				{
					triggered_events |= COREEVENT_AIR_JUMP;
					vel.y = -world->tuning.air_jump_impulse;
					jumped |= 3;
				}
			}
		}
		else
			jumped &= ~1;

		// handle hook
		if(input.hook)
		{
			if(hook_state == HOOK_IDLE)
			{
				hook_state = HOOK_FLYING;
				hook_pos = pos+target_direction*phys_size*1.5f;
				hook_dir = target_direction;
				hooked_player = -1;
				hook_tick = 0;
				triggered_events |= COREEVENT_HOOK_LAUNCH;
			}
		}
		else
		{
			hooked_player = -1;
			hook_state = HOOK_IDLE;
			hook_pos = pos;
		}
	}

	// add the speed modification according to players wanted direction
	if(direction < 0)
		vel.x = saturated_add(-max_speed, max_speed, vel.x, -accel);
	if(direction > 0)
		vel.x = saturated_add(-max_speed, max_speed, vel.x, accel);
	if(direction == 0)
		vel.x *= friction;

	// handle jumping
	// 1 bit = to keep track if a jump has been made on this input
	// 2 bit = to keep track if a air-jump has been made
	if(grounded)
		jumped &= ~2;

	// do hook
	if(hook_state == HOOK_IDLE)
	{
		hooked_player = -1;
		hook_state = HOOK_IDLE;
		hook_pos = pos;
	}
	else if(hook_state >= HOOK_RETRACT_START && hook_state < HOOK_RETRACT_END)
	{
		hook_state++;
	}
	else if(hook_state == HOOK_RETRACT_END)
	{
		hook_state = HOOK_RETRACTED;
		triggered_events |= COREEVENT_HOOK_RETRACT;
		hook_state = HOOK_RETRACTED;
	}
	else if(hook_state == HOOK_FLYING)
	{
		vec2 new_pos = hook_pos+hook_dir*world->tuning.hook_fire_speed;
		if(distance(pos, new_pos) > world->tuning.hook_length)
		{
			hook_state = HOOK_RETRACT_START;
			new_pos = pos + normalize(new_pos-pos) * world->tuning.hook_length;
		}

		// make sure that the hook doesn't go though the ground
		bool going_to_hit_ground = false;
		bool going_to_retract = false;
		int hit = col_intersect_line(hook_pos, new_pos, &new_pos, 0);
		if(hit)
		{
			if(hit&COLFLAG_NOHOOK)
				going_to_retract = true;
			else
				going_to_hit_ground = true;
		}

		// Check against other players first
		if(world && world->tuning.player_hooking)
		{
			float dist = 0.0f;
			for(int i = 0; i < MAX_CLIENTS; i++)
			{
				CHARACTER_CORE *p = world->characters[i];
				if(!p || p == this)
					continue;

				vec2 closest_point = closest_point_on_line(hook_pos, new_pos, p->pos);
				if(distance(p->pos, closest_point) < phys_size+2.0f)
				{
					if (hooked_player == -1 || distance (hook_pos, p->pos) < dist)
					{
						triggered_events |= COREEVENT_HOOK_ATTACH_PLAYER;
						hook_state = HOOK_GRABBED;
						hooked_player = i;
						dist = distance (hook_pos, p->pos);
					}
				}
			}
		}

		if(hook_state == HOOK_FLYING)
		{
			// check against ground
			if(going_to_hit_ground)
			{
				triggered_events |= COREEVENT_HOOK_ATTACH_GROUND;
				hook_state = HOOK_GRABBED;
			}
			else if(going_to_retract)
			{
				triggered_events |= COREEVENT_HOOK_HIT_NOHOOK;
				hook_state = HOOK_RETRACT_START;
			}

			hook_pos = new_pos;
		}
	}

	if(hook_state == HOOK_GRABBED)
	{
		if(hooked_player != -1)
		{
			CHARACTER_CORE *p = world->characters[hooked_player];
			if(p)
				hook_pos = p->pos;
			else
			{
				// release hook
				hooked_player = -1;
				hook_state = HOOK_RETRACTED;
				hook_pos = pos;
			}

			// keep players hooked for a max of 1.5sec
			//if(server_tick() > hook_tick+(server_tickspeed()*3)/2)
				//release_hooked();
		}

		// don't do this hook rutine when we are hook to a player
		if(hooked_player == -1 && distance(hook_pos, pos) > 46.0f)
		{
			vec2 hookvel = normalize(hook_pos-pos)*world->tuning.hook_drag_accel;
			// the hook as more power to drag you up then down.
			// this makes it easier to get on top of an platform
			if(hookvel.y > 0)
				hookvel.y *= 0.3f;

			// the hook will boost it's power if the player wants to move
			// in that direction. otherwise it will dampen everything abit
			if((hookvel.x < 0 && direction < 0) || (hookvel.x > 0 && direction > 0))
				hookvel.x *= 0.95f;
			else
				hookvel.x *= 0.75f;

			vec2 new_vel = vel+hookvel;

			// check if we are under the legal limit for the hook
			if(length(new_vel) < world->tuning.hook_drag_speed || length(new_vel) < length(vel))
				vel = new_vel; // no problem. apply

		}

		// release hook (max hook time is 1.25
		hook_tick++;
		if(hooked_player != -1 && (hook_tick > SERVER_TICK_SPEED+SERVER_TICK_SPEED/5 || !world->characters[hooked_player]))
		{
			hooked_player = -1;
			hook_state = HOOK_RETRACTED;
			hook_pos = pos;
		}
	}

	if(world && world->tuning.player_collision)
	{
		for(int i = 0; i < MAX_CLIENTS; i++)
		{
			CHARACTER_CORE *p = world->characters[i];
			if(!p)
				continue;

			//player *p = (player*)ent;
			if(p == this) // || !(p->flags&FLAG_ALIVE)
				continue; // make sure that we don't nudge our self

			// handle player <-> player collision
			float d = distance(pos, p->pos);
			vec2 dir = normalize(pos - p->pos);
			if(d < phys_size*1.25f && d > 1.0f)
			{
				float a = (phys_size*1.45f - d);

				// make sure that we don't add excess force by checking the
				// direction against the current velocity
				vec2 veldir = normalize(vel);
				float v = 1-(dot(veldir, dir)+1)/2;
				vel = vel + dir*a*(v*0.75f);
				vel = vel * 0.85f;
			}

			// handle hook influence
			if(hooked_player == i)
			{
				if(d > phys_size*1.50f) // TODO: fix tweakable variable
				{
					float accel = world->tuning.hook_drag_accel * (d/world->tuning.hook_length);
					float drag_speed = world->tuning.hook_drag_speed;

					// add force to the hooked player
					p->vel.x = saturated_add(-drag_speed, drag_speed, p->vel.x, accel*dir.x*1.5f);
					p->vel.y = saturated_add(-drag_speed, drag_speed, p->vel.y, accel*dir.y*1.5f);

					// add a little bit force to the guy who has the grip
					vel.x = saturated_add(-drag_speed, drag_speed, vel.x, -accel*dir.x*0.25f);
					vel.y = saturated_add(-drag_speed, drag_speed, vel.y, -accel*dir.y*0.25f);
				}
			}
		}
	}

	// clamp the velocity to something sane
	if(length(vel) > 6000)
		vel = normalize(vel) * 6000;
}
示例#5
0
文件: ctf.cpp 项目: blacktrader/CCity
void GAMECONTROLLER_CTF::tick()
{
	GAMECONTROLLER::tick();

	do_team_score_wincheck();
	do_race_time_check();
	
	for(int fi = 0; fi < 2; fi++)
	{
		FLAG *f = flags[fi];
		
		if(!f)
			continue;
		
		// flag hits death-tile, reset it
		if(col_get((int)f->pos.x, (int)f->pos.y)&COLFLAG_DEATH)
		{
			game.create_sound_global(SOUND_CTF_RETURN);
			f->reset();
			continue;
		}
		
		//
		if(f->carrying_character)
		{
			// update flag position
			f->pos = f->carrying_character->pos;
			
			if(flags[fi^1] && flags[fi^1]->at_stand)
			{
				if(distance(f->pos, flags[fi^1]->pos) < 32)
				{
					// CAPTURE! \o/
					teamscore[fi^1] += 100;
					f->carrying_character->player->score += 500;

					dbg_msg("game", "flag_capture player='%d:%s'",
						f->carrying_character->player->client_id,
						server_clientname(f->carrying_character->player->client_id));

					char buf[512];
					float capture_time = (server_tick() - f->grab_tick)/(float)server_tickspeed();
					if(capture_time <= 60)
					{
						str_format(buf, sizeof(buf), "the %s flag was captured by %s (%d.%s%d seconds)", fi ? "blue" : "red", server_clientname(f->carrying_character->player->client_id), (int)capture_time%60, ((int)(capture_time*100)%100)<10?"0":"", (int)(capture_time*100)%100);
					}
					else
					{
						str_format(buf, sizeof(buf), "the %s flag was captured by %s", fi ? "blue" : "red", server_clientname(f->carrying_character->player->client_id));
					}
					game.send_chat(-1, -2, buf);
					for(int i = 0; i < 2; i++)
						flags[i]->reset();
					
					game.create_sound_global(SOUND_CTF_CAPTURE);
				}
			}			
		}
		else
		{
			CHARACTER *close_characters[MAX_CLIENTS];
			int num = game.world.find_entities(f->pos, 32.0f, (ENTITY**)close_characters, MAX_CLIENTS, NETOBJTYPE_CHARACTER);
			for(int i = 0; i < num; i++)
			{
				if(!close_characters[i]->alive || close_characters[i]->player->team == -1 || col_intersect_line(f->pos, close_characters[i]->pos, NULL, NULL))
					continue;
				
				if(close_characters[i]->team == f->team)
				{
					// return the flag
					if(!f->at_stand)
					{
						CHARACTER *chr = close_characters[i];
						chr->player->score += 100;

						dbg_msg("game", "flag_return player='%d:%s'",
							chr->player->client_id,
							server_clientname(chr->player->client_id));

						game.create_sound_global(SOUND_CTF_RETURN);
						f->reset();
					}
				}
				else
				{
					// take the flag
					if(f->at_stand)
					{
						teamscore[fi^1]++;
						f->grab_tick = server_tick();
					}
					f->at_stand = 0;
					f->carrying_character = close_characters[i];
					f->carrying_character->player->score += 300;

					dbg_msg("game", "flag_grab player='%d:%s'",
						f->carrying_character->player->client_id,
						server_clientname(f->carrying_character->player->client_id));
					
					for(int c = 0; c < MAX_CLIENTS; c++)
					{
						if(!game.players[c])
							continue;
							
						if(game.players[c]->team == fi)
							game.create_sound_global(SOUND_CTF_GRAB_EN, game.players[c]->client_id);
						else
							game.create_sound_global(SOUND_CTF_GRAB_PL, game.players[c]->client_id);
					}
					break;
				}
			}
			
			if(!f->carrying_character && !f->at_stand)
			{
				if(server_tick() > f->drop_tick + server_tickspeed()*30)
				{
					game.create_sound_global(SOUND_CTF_RETURN);
					f->reset();
				}
				else
				{
					f->vel.y += game.world.core.tuning.gravity;
					move_box(&f->pos, &f->vel, vec2(f->phys_size, f->phys_size), 0.5f);
				}
			}
		}
	}
}