示例#1
8
bool GameChat::handle_special_commands(GameState* gs,
		const std::string& command) {
	ChatMessage printed;
	const char* content;
	PlayerInst* p = gs->local_player();

	//Spawn monster
	if (starts_with(command, "!spawn ", &content)) {
		const char* rest = content;
		int amnt = strtol(content, (char**)&rest, 10);
		if (content == rest)
			amnt = 1;
		rest = skip_whitespace(rest);

		int enemy = get_enemy_by_name(rest, false);
		if (enemy == -1) {
			printed.message = "No such monster, '" + std::string(rest) + "'!";
			printed.message_colour = Colour(255, 50, 50);
		} else {
			printed.message = std::string(rest) + " has spawned !";
			generate_enemy_after_level_creation(gs, enemy, amnt);
			printed.message_colour = Colour(50, 255, 50);
		}
		add_message(printed);
		return true;
	}

	//Set game speed
	if (starts_with(command, "!gamespeed ", &content)) {
		int gamespeed = squish(atoi(content), 1, 200);
		gs->game_settings().time_per_step = gamespeed;
		printed.message = std::string("Game speed set.");
		printed.message_colour = Colour(50, 255, 50);
		add_message(printed);
		return true;
	}

	//Gain XP
	if (starts_with(command, "!gainxp ", &content)) {
		int xp = atoi(content);
		if (xp > 0 && xp < 999999) {
			printed.message = std::string("You have gained ") + content
					+ " experience.";
			printed.message_colour = Colour(50, 255, 50);
			add_message(printed);
			p->gain_xp(gs, xp);
		} else {
			printed.message = "Invalid experience amount!";
			printed.message_colour = Colour(255, 50, 50);
			add_message(printed);
		}
		return true;
	}

	//Create item
	if (starts_with(command, "!item ", &content)) {
		const char* rest = content;
		int amnt = strtol(content, (char**)&rest, 10);
		if (content == rest)
			amnt = 1;
		rest = skip_whitespace(rest);

		int item = get_item_by_name(rest, false);
		if (item == -1) {
			printed.message = "No such item, '" + std::string(rest) + "'!";
			printed.message_colour = Colour(255, 50, 50);
		} else {
			printed.message = std::string(rest) + " put in your inventory !";
			p->stats().equipment.inventory.add(Item(item), amnt);
			printed.message_colour = Colour(50, 255, 50);
		}
		add_message(printed);
		return true;
	}

	//Kill all monsters
	if (starts_with(command, "!killall", &content)) {
		MonsterController& mc = gs->monster_controller();
		for (int i = 0; i < mc.monster_ids().size(); i++) {
			EnemyInst* inst = (EnemyInst*)gs->get_instance(mc.monster_ids()[i]);
			if (inst) {
				inst->damage(gs, 99999);
			}
		}
		printed.message = "Killed all monsters.";
		printed.message_colour = Colour(50, 255, 50);
		add_message(printed);
		return true;
	}

	lua_State* L = gs->get_luastate();
	static LuaValue script_globals;
	if (script_globals.empty()) {
		script_globals.table_initialize(L);
//		script_globals.push(L);
//		int script = lua_gettop(L);
//		lua_pushvalue(L, LUA_GLOBALSINDEX);
//		lua_setmetatable(L, script);
//		lua_pop(L, 1);
	}

	lua_push_gameinst(L, p);
	script_globals.table_pop_value(L, "player");
	lua_push_combatstats(L, p);
	script_globals.table_pop_value(L, "stats");

	//Run lua command
	if (starts_with(command, "!lua ", &content)) {
//		std::string luafunc = std::string(content);

		int prior_top = lua_gettop(L);

		luaL_loadstring(L, content);
		if (lua_isstring(L, -1)) {
			const char* val = lua_tostring(L, -1);
			add_message(val, /*iserr ? Colour(255,50,50) :*/
			Colour(120, 120, 255));
			return true;
		}

		int lfunc = lua_gettop(L);
		script_globals.push(L);
		lua_setfenv(L, lfunc);

		bool iserr = (lua_pcall(L, 0, LUA_MULTRET, 0) != 0);

		int current_top = lua_gettop(L);

		for (; prior_top < current_top; prior_top++) {
			if (lua_isstring(L, -1)) {
				const char* val = lua_tostring(L, -1);
				add_message(val,
						iserr ? Colour(255, 50, 50) : Colour(120, 120, 255));
			}
			lua_pop(L, 1);
		}

		return true;
	}
	//Run lua file
	if (starts_with(command, "!luafile ", &content)) {
		int prior_top = lua_gettop(L);

		int err_func = luaL_loadfile(L, content);
		if (err_func) {
			const char* val = lua_tostring(L, -1);
			add_message(val, Colour(120, 120, 255));
			lua_pop(L, 1);
			return true;
		}

		int lfunc = lua_gettop(L);
		script_globals.push(L);
		lua_setfenv(L, lfunc);

		bool err_call = (lua_pcall(L, 0, 0, 0) != 0);
		if (err_call) {
			const char* val = lua_tostring(L, -1);
			add_message(val, Colour(120, 120, 255));
			lua_pop(L, 1);
		}
		return true;
	}

	return false;
}
示例#2
0
void MonsterController::register_enemy(GameInst* enemy) {
	mids.push_back(enemy->id);
	RVO::Vector2 enemy_position(enemy->x, enemy->y);
	EnemyInst* e = (EnemyInst*)enemy;
	EffectiveStats& estats = e->effective_stats();
	EnemyBehaviour& eb = e->behaviour();
}
示例#3
0
void MonsterController::post_draw(GameState* gs) {
	PlayerInst* player = gs->local_player();
	if (!player) {
		return;
	}
	EnemyInst* target = (EnemyInst*)gs->get_instance(player->target());
	if (!target) {
		return;
	}

	ldraw::draw_circle_outline(COL_GREEN.alpha(140),
			on_screen(gs, target->ipos()), target->target_radius + 5, 2);
}
示例#4
0
static void push_inst_name(lua_State* L, GameInst* inst) {
	PlayerInst* p = dynamic_cast<PlayerInst*>(inst);
	if (p) {
//		lua_pushlstring(L, p->); //TODO
		lua_pushstring(L, "Your ally");
	} else {
		EnemyInst* e = dynamic_cast<EnemyInst*>(inst);
		if (e) {
			std::string& name = e->etype().name;
			lua_pushlstring(L, name.c_str(), name.size());
		} else {
			lua_pushnil(L);
		}
	}
}
void PlayerInst::use_weapon(GameState* gs, const GameAction& action) {
    WeaponEntry& wentry = weapon().weapon_entry();
    MTwist& mt = gs->rng();
    const int MAX_MELEE_HITS = 10;
    EffectiveStats& estats = effective_stats();
    if (!cooldowns().can_doaction()) {
        return;
    }

    Pos start(x, y);
    Pos actpos(action.action_x, action.action_y);

    if (wentry.uses_projectile && !equipment().has_projectile()) {
        return;
    }

    int cooldown = 0;

    if (equipment().has_projectile()) {
        const Projectile& projectile = equipment().projectile;
        ProjectileEntry& pentry = projectile.projectile_entry();
        item_id item = get_item_by_name(pentry.name.c_str());
        int weaprange = std::max(wentry.range, pentry.range);

        AttackStats weaponattack(weapon());

        bool wallbounce = false;
        int nbounces = 0;
        float movespeed = pentry.speed;

        cooldown = std::max(wentry.cooldown, pentry.cooldown);

        //XXX: Horrible hack REMOVE THIS LATER
        if (class_stats().class_type().name == "Archer"
                && pentry.weapon_class == "bows") {
            int xplevel = class_stats().xplevel;
            float movebonus = class_stats().xplevel / 4.0f;
            if (movebonus > 2) {
                movebonus = 2;
            }
            float cooldown_mult = 1.0f - (class_stats().xplevel - 1) / 20.0f;
            if (cooldown_mult <= 0.85) {
                cooldown_mult = 0.85;
            }
            cooldown *= cooldown_mult;
            movespeed += movebonus;
            if (xplevel >= 3 && core_stats().mp >= 5) {
                nbounces = 2;
                core_stats().mp -= 5;
            }
        }

        GameInst* bullet = new ProjectileInst(projectile,
                                              effective_atk_stats(mt, weaponattack), id, start, actpos,
                                              movespeed, weaprange, NONE, wallbounce, nbounces);
        gs->add_instance(bullet);
        equipment().use_ammo();
    } else {
        int weaprange = wentry.range + this->radius + TILE_SIZE / 2;
        float mag = distance_between(actpos, Pos(x, y));
        if (mag > weaprange) {
            float dx = actpos.x - x, dy = actpos.y - y;
            actpos = Pos(x + dx / mag * weaprange, y + dy / mag * weaprange);
        }

        GameInst* enemies[MAX_MELEE_HITS];

        int max_targets = std::min(MAX_MELEE_HITS, wentry.max_targets);

        int numhit = get_targets(gs, this, actpos.x, actpos.y, wentry.dmgradius,
                                 enemies, max_targets);

        if (numhit == 0) {
            return;
        }

        for (int i = 0; i < numhit; i++) {
            EnemyInst* e = (EnemyInst*)enemies[i];
            lua_hit_callback(gs->get_luastate(), wentry.on_hit_func, this, e);
            if (attack(gs, e, AttackStats(equipment().weapon))) {
                PlayerData& pc = gs->player_data();
                signal_killed_enemy();

                char buffstr[32];
                int amnt = round(
                               double(e->xpworth()) / pc.all_players().size());
                players_gain_xp(gs, amnt);
                snprintf(buffstr, 32, "%d XP", amnt);
                gs->add_instance(
                    new AnimatedInst(Pos(e->x - 5, e->y - 5), -1, 25,
                                     Posf(), Posf(), AnimatedInst::DEPTH, buffstr,
                                     Colour(255, 215, 11)));
            }
        }
        cooldown = wentry.cooldown;
    }

    cooldowns().reset_action_cooldown(cooldown * estats.cooldown_mult);

    reset_rest_cooldown();
}
示例#6
0
void MonsterController::pre_step(GameState* gs) {
	perf_timer_begin(FUNCNAME);

	CollisionAvoidance& coll_avoid = gs->collision_avoidance();
	PlayerInst* local_player = gs->local_player();
	std::vector<EnemyOfInterest> eois;

	players = gs->players_in_level();

	//Update 'mids' to only hold live objects
	std::vector<obj_id> mids2;
	mids2.reserve(mids.size());
	mids.swap(mids2);

	for (int i = 0; i < mids2.size(); i++) {
		EnemyInst* e = (EnemyInst*)gs->get_instance(mids2[i]);
		if (e == NULL)
			continue;
		EnemyBehaviour& eb = e->behaviour();
		eb.step();

		//Add live instances back to monster id list
		mids.push_back(mids2[i]);

		int closest_player_index = find_player_to_target(gs, e);

		if (eb.current_action == EnemyBehaviour::INACTIVE
				&& e->cooldowns().is_hurting()) {
			eb.current_action = EnemyBehaviour::CHASING_PLAYER;
		}
		if (closest_player_index == -1
				&& eb.current_action == EnemyBehaviour::CHASING_PLAYER) {
			eb.current_action = EnemyBehaviour::INACTIVE;
			e->target() = NONE;
		}

		if (eb.current_action == EnemyBehaviour::CHASING_PLAYER)
			eois.push_back(
					EnemyOfInterest(e, closest_player_index,
							inst_distance(e, players[closest_player_index])));
		else if (eb.current_action == EnemyBehaviour::INACTIVE)
			monster_wandering(gs, e);
		else
			//if (eb.current_action == EnemyBehaviour::FOLLOWING_PATH)
			monster_follow_path(gs, e);
	}

	set_monster_headings(gs, eois);

	//Update player positions for collision avoidance simulator
	for (int i = 0; i < players.size(); i++) {
		PlayerInst* p = players[i];
		coll_avoid.set_position(p->collision_simulation_id(), p->x, p->y);
	}

	for (int i = 0; i < mids.size(); i++) {
		EnemyInst* e = (EnemyInst*)gs->get_instance(mids[i]);
		lua_State* L = gs->luastate();
		lua_gameinst_callback(L, e->etype().step_event.get(L), e);
		update_velocity(gs, e);
		simul_id simid = e->collision_simulation_id();
		coll_avoid.set_position(simid, e->rx, e->ry);
		coll_avoid.set_preferred_velocity(simid, e->vx, e->vy);
	}

	coll_avoid.step();

	for (int i = 0; i < mids.size(); i++) {
		EnemyInst* e = (EnemyInst*)gs->get_instance(mids[i]);
		update_position(gs, e);
	}

	perf_timer_end(FUNCNAME);
}