/include/civilian.h (02213236475a338c5fe65202a80f80eef71fc367) (4594 bytes) (mode 100755) (type blob)
#ifndef CIVILIAN_H
#define CIVILIAN_H
#ifndef FWORLD_H
#error Include fworld.h before civilian.h so the world can be referenced.
#endif
#include <stdio.h>
#include <cmath>
#include <cstdlib>
#include <vector>
namespace civilian {
struct Civilian {
size_t entity_index;
};
fworld::Entity* FindPOI(
fworld::World* world,
fworld::Entity &entity );
void AI(
std::vector<Civilian>* civilians,
fworld::World* world,
unsigned int rand_seed,
double d );
std::vector<Civilian> GetCivilians( fworld::World* world );
fworld::Entity* FindPOI(
fworld::World* world,
fworld::Entity &entity ){
// Make a list of possible points of interest.
std::vector<fworld::Entity*> candidates;
for( auto &e : world->entities ){
long long tile_x = e.x + 0.5, tile_y = e.y + 0.5;
if( e.task != fworld::TASK_SLEEP
&& ( e.type.length() < 4 || ( e.type.substr( 0, 4 ) != "WARP"
&& ( e.type.length() < 6 || e.type.substr( 0, 6 ) != "portal" )
&& e.type != "ignore"
&& e.type != "base"
&& e.type != "corpse"
&& e.type != "fighter"
&& e.type != "sentry"
&& e.type != "flora"
&& e.type != "pickup"
&& e.type != "regrow"
&& e.type != "spawn"
&& e.type != "player" ) )
&& !world->entitiesBumping( entity, e )
&& !world->tileBlocking( tile_x, tile_y, true )
&& world->reachable( (long long)( entity.x + 0.5 ), (long long)( entity.y + 0.5 ), tile_x, tile_y, 15, true ) ){
candidates.push_back( &e );
}
}
// Randomly pick a point of interest.
if( candidates.size() > 0 ){
return candidates[(double)std::rand() / RAND_MAX * candidates.size()];
}
return nullptr;
}
void AI(
std::vector<Civilian>* civilians,
fworld::World* world,
unsigned int rand_seed,
double d ){
std::srand( rand_seed );
// Define the player variable.
fworld::Entity* player = nullptr;
// This lambda has access to the player and the world.
auto TalkingToPlayer = [&]( fworld::Entity &entity ){
// Check that the player is in talk mode and has a path.
if( player->task == fworld::TASK_TALK && player->path.size() > 0 ){
// Get a target from the player's path.
intptr_t index = (intptr_t)player->path[player->path.size() - 1];
size_t map_width = world->mapInfo[0].size();
long long target_y = index / map_width;
long long target_x = index - target_y * map_width;
// Return whether the player is targeting the entity's position.
return target_x == (long long)( entity.x + 0.5 )
&& target_y == (long long)( entity.y + 0.5 );
}
return false;
};
// Find the player.
if( world->followEntity >= 0 ){
player = &world->entities[world->followEntity];
}
// Perform AI logic on all of the civilians.
for( auto &c : *civilians ){
if( c.entity_index >= world->entities.size() || (
world->entities[c.entity_index].type != "civilian"
&& world->entities[c.entity_index].type != "bird"
) ){
// Entity misalignment. Reassign civilians.
// The less this happens, the better. TODO
#ifndef __EMSCRIPTEN__
//fprintf( stderr, "Civilians misaligned. Correcting.\n" );
#endif
*civilians = GetCivilians( world );
return;
}
auto &ent = world->entities[c.entity_index];
if( player && player->task != fworld::TASK_SLEEP
&& ( TalkingToPlayer( ent )
|| ( ent.type != "bird"
&& world->entitiesBumping( ent, *player ) ) ) ){
// Entity is interacting with the player.
world->entityLookAt( ent, *player );
ent.path.clear();
ent.walking = false;
ent.task = fworld::TASK_NONE;
ent.boredom = 0.0;
}else if( ent.task == fworld::TASK_NONE || ent.path.size() == 0 ){
// Entity is standing still away from the player.
ent.task = fworld::TASK_NONE;
ent.boredom += d;
double patience = ent.type == "bird" ? 0.0 : 2.0;
if( ent.boredom >= patience ){
ent.boredom = 0.0;
fworld::Entity* poi = FindPOI( world, ent );
if( poi ){
ent.task = fworld::TASK_BUMP;
world->solveEntityPath(
ent,
(long long)( poi->x + 0.5 ),
(long long)( poi->y + 0.5 ),
true
);
}
}
}
// Stop the entity's walking animation if not walking.
if( ent.path.size() == 0 ){
ent.walking = false;
ent.frame = 0.0;
}
}
}
std::vector<Civilian> GetCivilians( fworld::World* world ){
std::vector<Civilian> civilians;
for( size_t i = 0; i < world->entities.size(); i++ ){
auto &ent = world->entities[i];
if( ent.type == "civilian" || ent.type == "bird" ){
Civilian c = {};
c.entity_index = i;
ent.task = fworld::TASK_NONE;
civilians.push_back( c );
}
}
return civilians;
}
} // namespace civilian
#endif // CIVILIAN_H
Mode |
Type |
Size |
Ref |
File |
100644 |
blob |
98 |
227abf3bfa53b2530dcc74495da7bd0ccdcb0775 |
.gitignore |
100644 |
blob |
225 |
9b00c2c2e7b4f0c1e338fdead65f17ba0af089c1 |
COPYING |
100755 |
blob |
43 |
45aea818a4a3202b2467509f28a481cce08834d2 |
Confectioner.command |
100644 |
blob |
12084 |
ca1d7e8e522f844c345c314ce6900efe486c41b5 |
Makefile |
100644 |
blob |
2723 |
b5a3f573f076ef740ca742ec9598043732e10c0e |
README.md |
040000 |
tree |
- |
f854ec266095e18d4bee80b61191f009190533d9 |
base |
100755 |
blob |
156 |
84cb1387849f2ca98e53e43536d00af2dfabf7d3 |
caveconfec |
100755 |
blob |
28 |
41b0ef285892c86306eaa269f366dd04cb633d21 |
caveconfec.bat |
100644 |
blob |
195275 |
7dd3fffe9bb73069112dc76fcecd405fdc0c8235 |
confec.cpp |
100644 |
blob |
391231 |
cae78a24f09285accda1bd45c3361d92f4d55946 |
gamecontrollerdb.txt |
040000 |
tree |
- |
a24928103d3d2c1929d85ab70447ac50d45a2384 |
include |
100755 |
blob |
1041 |
dd7c0bd7d8a6b4aeff53142375240872735d42a0 |
libs.cpp |
100755 |
blob |
27581 |
8350a63e947e8a4a55608fd090d128fef7b969a1 |
micropather.cpp |
100644 |
blob |
141235 |
f54e2d2631a628876a631456c043b77da5db78bd |
openjdk.pem |
100755 |
blob |
8 |
e9a74187b02a27b165dfa4f93bf6f060376d0ee6 |
steam_appid.txt |
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/mse/ConfectionerEngine
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/mse/ConfectionerEngine
Clone this repository using git:
git clone git://git.rocketgit.com/user/mse/ConfectionerEngine
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main